前回のTCP編 の続きとしてUDP通信によるShring通信に関しても書いておきます.
UDPでの利点,欠点
TCPを使ったネットワーク通信ではサーバー側のIPアドレスをクライアント側が知っておく必要がありました.
そのためローカルホスト内のネットワーク通信でもネットワーク環境が変わるとサーバーアドレスを入力する必要が出てきます.
またTCPは通信方式の関係で通信上の遅延が発生する場合があります.
UDP通信ではデータ受信の確認を行わないためTCPより遅延が少ない可能性があります.
また通信相手を指定せずにローカルネットワークすべてにデータを送信するブロードキャスト送信が行えるため,送信先アドレスを知らなくてもネットワーク通信が行えます.
しかし,UDP通信ではローカルネットワークのセキュリティ上通信を許可していない場合があります.
UDPによるブロードキャスト通信には
送信側デバイスがUDPブロードキャスト送信を許可している
通信を中継するルーターがUDP通信とブロードキャスト送受信を許可している
受信側デバイスがUDPブロードキャスト受信を許可している
以上の条件を確認する必要があります.
Windowsではさらに
ファイアーウォールが通信用ソフトウェアのUDP送受信を許可している
を確認する必要があります.
またポート番号だけはあらかじめ指定しておく必要があります.
自前で実装
UDP通信でもTCPと同様にUnityで利用できるC#関数とHoloLensなどUWPで利用できるC#関数が異なります.
Unity編
Unity側では前回同様Thread による非同期処理を行い,UdpClient によるUDP送受信を行っています.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Text;
public class UdpNetworkClientManager
{
private UdpClient udpclient;
public UdpNetworkClientManager(int port)
{
udpclient = new UdpClient();
udpclient.EnableBroadcast = true;
udpclient.Connect(new IPEndPoint(IPAddress.Broadcast, port));
}
public void SendMessage(string data)
{
Thread thread = new Thread(() =>
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
udpclient.Send(bytes, bytes.Length);
});
thread.Start();
}
}
UdpClient
を作成しブロードキャスト通信の許可とブロードキャストアドレス,ポート番号を指定します.
データ送信時にはSendMessage(string data)
から非同期処理によって送信を行います.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
using System;
using System.Net;
using System.Threading;
using System.Net.Sockets;
using System.Text;
public class UdpNetworkListenManager
{
private Thread thread = null;
public UdpNetworkListenManager(int port)
{
thread = new Thread(()=> {
UdpClient udpclient = new UdpClient(port);
IPEndPoint remote = new IPEndPoint(IPAddress.Any, port);
try
{
byte[] bytes = udpclient.Receive(ref remote);
string ms = Encoding.UTF8.GetString(bytes);
}
catch (Exception) { }
udpclient.Close();
});
thread.Start();
}
}
送信時と同様に非同期処理中にUdpClient
を作成しポートを指定します.
Receive
によってデータを受信しstring ms
にテキストデータとして受け取ります.
HoloLens編
HoloLensなどUWP環境では非同期処理にTask ,UDPデータ送受信にDatagramSocket を利用します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
using System.Net;
#if UNITY_UWP
using System;
using System.IO;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
#endif
public class UdpNetworkClientManager
{
#if UNITY_UWP
private StreamWriter writer=null;
#endif
public UdpNetworkClientManager(int port)
{
#if UNITY_UWP
Task.Run(async () =>
{
DatagramSocket socket = new DatagramSocket();
string Address = IPAddress.Broadcast.ToString();
var datagram = await socket.GetOutputStreamAsync(new HostName(Address), port.ToString());
writer = new StreamWriter(datagram.AsStreamForWrite());
});
#endif
}
public void SendMessage(string data)
{
#if UNITY_UWP
if (writer != null) Task.Run(async () =>
{
await writer.WriteAsync(data);
await writer.FlushAsync();
});
#endif
}
}
非同期処理中にDatagramSocket
を作成しブロードキャストアドレスとポート番号を指定します.
SendMessage(string data)
よりデータを送信します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
using System;
#if UNITY_UWP
using System.IO;
using System.Threading.Tasks;
using Windows.Networking.Sockets;
#endif
public class UdpNetworkListenManager
{
#if UNITY_UWP
private DatagramSocket socket = null;
#endif
public UdpNetworkListenManager(int port)
{
#if UNITY_UWP
Task.Run(async () =>
{
socket = new DatagramSocket();
socket.MessageReceived += MessageReceived;
await socket.BindServiceNameAsync(port.ToString());
});
#endif
}
#if UNITY_UWP
async void MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
StreamReader reader = new StreamReader(args.GetDataStream().AsStreamForRead());
string ms = await reader.ReadLineAsync();
}
#endif
}
送信時と同様にDatagramSocket
を作成しポートを指定します.
作成時にデータ受信時に呼ばれるイベントを登録します.
データ受信時にMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
が呼ばれstring ms
にデータを受け取ります.
HoloLensなどUWP環境ではTCP編 同様に通信機能の許可が必要になるため,UnityEditorまたはVisualStudio上で機能の許可を設定してください.
まとめ
実行環境ごとの切り分けが大変
UDPブロードキャスト通信ができる環境なら比較的簡単に通信ができる
今回の実装に関しては自前の HoloLensModule にて複数台接続に対応したものを入れています.