03/02

03/02

# 研究目的

  • ゲームの通信方式にはクライアントサーバ方式とp2p方式がある
  • データの安全性やチート対策などでクライアントサーバ方式が主流
  • サーバに接続してマルチプレイなどのデータ同期を実現させているため、低速
  • 高速かつ安全に通信を行たい
    • 並列分散フレームワークChristieがある
    • Christieを利用してp2pで通信を行う
  • ゲーム開発で主に使用されているUnityに対応するためにChristieをC#へ書き換えを行う

# ここ1ヶ月の進捗

  • 卒論発表、修論審査お疲れ様でした
  • ChristieのHelloWorldを動かすために必要なコードを書き切った(1/26)
    • 案の定動かない
    • どうもFinishCodeGearが実行されていない
      • Task周りの問題?
    • デバッグをしつつ、ChristieのCodegear, Datagearがどう生成されてどういう風に動作しているかコードを追ってみている

# Christie

1
2
3
4
5
6
/usr/local/share/dotnet/dotnet /Users/e165729/konoLab/Christie_net/bin/Debug/netcoreapp3.1/Christie_net.dll
ChristieDaemon, listen: bind to [::1]:10000
HelloWorldCodeGear Take => 
HelloWorldCodeGear Take => 

Process finished with exit code 0.

エラーも出ずに終了してしまう。

1
2
3
4
5
6
7
public static void Main(string[] args) {
  CodeGearManager cgm = CreateCgm(10000);
  cgm.Setup(new HelloWorldCodeGear());
  cgm.Setup(new FinishHelloWorld());
  cgm.GetLocalDGM().Put("helloWorld", "hello");
  cgm.GetLocalDGM().Put("helloWorld", "world");
    }
1
2
3
4
5
6
7
8
9
public class HelloWorldCodeGear : CodeGear {
    [Take] private string helloWorld;
    
    public override void Run(CodeGearManager cgm) {
        Console.WriteLine("HelloWorldCodeGear Take => " +helloWorld);
        cgm.Setup(new HelloWorldCodeGear());
        cgm.GetLocalDGM().Put(helloWorld, helloWorld);
    }
}
1
2
3
4
5
6
7
8
9
public class FinishHelloWorld : CodeGear {
    [Take] private string hello;
    [Take] private string world;

    public override void Run(CodeGearManager cgm) {
        Console.WriteLine("fin:" + hello + " " + world);
        cgm.GetLocalDGM().Finish();
    }
}

# 優先度つきTreadPoolについて

Taskは内部的にThreadPoolを使っている
Task生成時にTaskSchedulerを指定できる
→TaskSchedulerを継承して自作する →内部のwaitQueueの順番を操作することが可能
→java版と同じように優先度がつけれそう

# リフレクションで死んでしまった

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
foreach (var field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | 
                                                       BindingFlags.DeclaredOnly | BindingFlags.Instance)) {
            if (Attribute.IsDefined(field, typeof(Take))) {
                SetCommand(CommandType.TAKE, "local", field.Name, new DataGear<object>(field.FieldType));
            } else if (Attribute.IsDefined(field, typeof(Peek))) {
                SetCommand(CommandType.PEEK, "local", field.Name, new DataGear<object>(field.FieldType));
            } else if (Attribute.IsDefined(field, typeof(TakeFrom))) {
                TakeFrom attri = (TakeFrom) field.GetCustomAttribute(typeof(TakeFrom));
                SetCommand(CommandType.TAKE, attri.name, field.Name, new DataGear<object>(field.FieldType));
            } else if (Attribute.IsDefined(field, typeof(PeekFrom))) {
                PeekFrom attri = (PeekFrom) field.GetCustomAttribute(typeof(PeekFrom));
                SetCommand(CommandType.PEEK, attri.name, field.Name, new DataGear<object>(field.FieldType));
            }
        }

DataGear<object>(field.GetType())だとtypeがRuntimeTypeになってしまった。
fieldのメンバにFieldTypeがあったのでそれを使ったら直った。


# IPAddressが0だと死ぬ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// listen on any address ipv4/ipv6
            IPHostEntry host = Dns.GetHostEntry("::");
            IPAddress ipAddress = host.AddressList[0];
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, localPort);

            Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            Console.WriteLine("ChristieDaemon, listen: bind to " + localEndPoint);
            socket.Bind(localEndPoint);
            socket.Listen((int)SocketOptionName.MaxConnections);

IPHostEntry host = Dns.GetHostEntry("::");だとダメ
IPHostEntry host = Dns.GetHostEntry("::1");で一応動いている。

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy