LoginSignup
8
9

More than 5 years have passed since last update.

2015-09-04 unity > udpMonitor > UDPのrelay機能の実装 / 通信内容export機能付き

Last updated at Posted at 2015-09-04
実装
Unity 5.1.2-f1 on MacOS X 10.8.5

二台の端末があり、ポート6000でUDP通信をしているとする。

  • 192.168.10.5
    • 文字列を送信して応答を受信する
  • 192.168.10.6
    • echo serverが起動している

その間に(192.168.10.3として)入って、通信をリレーする処理を実装してみた。

v0.3 @ github

主な処理は以下のコード

udpMonitorScript.cs
    void DoRelay() {
        UdpClient client = new UdpClient (setPort);
        client.Client.ReceiveTimeout = 300; // msec
        client.Client.Blocking = false;

        int portToReturn = 31415; // is set dummy value at first
        while (ToggleComm.isOn) {
            try {
                IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                byte[] data = client.Receive(ref anyIP);
                string text = Encoding.ASCII.GetString(data);

                if (text.Length == 0) {
                    Thread.Sleep(20);
                    continue;
                }
                string fromIP = anyIP.Address.ToString();
                int fromPort = anyIP.Port;

                // send to the other
                if (fromIP.Equals(ipadr1)) {
                    portToReturn = fromPort; // store the port used in the "else" clause
                    client.Send(data, data.Length, ipadr2, setPort);
                    DebugPrintComm("1 ", fromIP, fromPort, ipadr2, setPort);
                } else {
                    client.Send(data, data.Length, ipadr1, portToReturn);
                    DebugPrintComm("2 ", fromIP, fromPort, ipadr1, portToReturn);
                }
            }
            catch (Exception err) {

            }
            // without this sleep, on android, the app will freeze at Unity splash screen
            Thread.Sleep(200);
        }
        client.Close ();
    }

Unityプロジェクトの使用例

192.168.10.3の端末で起動するとする。

起動直後
Main_unity_-_150831-udpMonitor_-_PC__Mac___Linux_Standalone__Personal_.jpg

Settingボタンを押すして、以下の設定を入力する。

Main_unity_-_150831-udpMonitor_-_PC__Mac___Linux_Standalone__Personal_.jpg

OKボタンを押して、最初のシーンに戻る。

Main_unity_-_150831-udpMonitor_-_PC__Mac___Linux_Standalone__Personal_.jpg

ToggleCommにチェックを入れると、Relay機能が有効になる。

192.168.10.5の端末から 192.168.10.3(ポート6000)宛のUDP通信を行うと、以下の動作になる

  • 192.168.10.3が受信した文字を 192.168.10.6へ送る (relay)
  • 192.168.10.6が受信した文字を 192.168.10.3へ送り返す (echo server起動している時)
  • 192.168.10.3が受信した文字を 192.168.10.5へ送る (relay)

Main_unity_-_150831-udpMonitor_-_PC__Mac___Linux_Standalone__Personal_.jpg

苦労した点

UDPのポート番号の理解がいまいちだったため、6000から6000へ送ろうとして失敗していた。

v0.5 (通信データexport機能追加)

v0.5 @ github

以下のコマンドで通信データを出力する機能を追加した。

export,88555bd

88555bdというのはv0.1 commit時のhash. 普段の通信では使われることはないだろうという理由から選択した。

使用例

IP:192.168.10.3において、以下の設定でソフトを起動しているとする (192.168.10.8から192.168.10.5の通信をモニタする)。

Main_unity_-_150831-udpMonitor_-_Android__Personal_.jpg

今回の例では、192.168.10.5においてecho serverを起動している。

192.168.10.8から 192.168.10.3へ以下のようにUDPで文字列を送信する。

$ echo "testaaa" | nc -w 2 -u 192.168.10.3 6000
testaaa
$ echo "testaaa" | nc -w 2 -u 192.168.10.3 6000
testaaa
$ echo "testaaa" | nc -w 2 -u 192.168.10.3 6000
testaaa

192.168.10.8(送信元)においてexpotコマンドを使うと、それまで送受信した文字列が送受信時刻、送受信方向とともに取得できる。

$ echo "export,88555bd" | nc -w 2 -u 192.168.10.3 6000
SOT
2015/09/13 03:34:18,tx,testaaa
2015/09/13 03:34:18,rx,testaaa
2015/09/13 03:34:23,tx,testaaa
2015/09/13 03:34:23,rx,testaaa
2015/09/13 03:34:26,tx,testaaa
2015/09/13 03:34:26,rx,testaaa
EOT

SOT: start of table, EOT:end of table
tx: 192.168.10.8 -> 192.168.10.5の通信
rx: 192.168.10.5 -> 192.168.10.8の通信

実装

以下のようなListに通信内容を保持していく。
list_comm_stringには"tx,"か"rx,"かと送受信のtextを格納する。

private List<System.DateTime> list_comm_time;
private List<string> list_comm_string;

exportData()の処理は以下。時系列グラフ udpTimeGraphでやっていることとほぼ同じ。

udpMonitorScript.cs
...
    private void exportData(ref UdpClient client, ref IPEndPoint anyIP) 
    {
        byte[] data;
        string text;

        int idx = 0;

        text = "SOT"; // start of table
        text = text + System.Environment.NewLine;
        data = System.Text.Encoding.ASCII.GetBytes(text);
        client.Send(data, data.Length, anyIP);

        foreach (var commtime in list_comm_time) {
            text = commtime.ToString("yyyy/MM/dd HH:mm:ss");
            text = text + ",";
            text = text + list_comm_string[idx];

            // below comment out because text already includes <CR><LF>
    //      text = text + System.Environment.NewLine;

            data = System.Text.Encoding.ASCII.GetBytes (text);
            client.Send (data, data.Length, anyIP);

            idx++;
        }

        text = "EOT"; // start of table
        text = text + System.Environment.NewLine;
        data = System.Text.Encoding.ASCII.GetBytes(text);
        client.Send(data, data.Length, anyIP);

    }
...

不明点

192.168.10.8と192.168.10.5が192.168.10.3経由で通信を続けている時に、別のIPから192.168.10.3に向けてexportコマンドを発行した時の動作が未調査。

とりあえずはexportコマンド発行時は他の通信を停止しているのがよいかも。

今後

  1. DONE: リレーした文字列を格納、取出しする
  2. DONE: リレー時に遅延処理を入れる (通信状況が悪い場合の再現)
  3. UIまわりをよくしようかどうか。優先度は低い。

検索用キーワード

(2019-01-18追記)

  • UDPrepeater
  • UDPrelay
8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9