UDP通信をテストするために2つの小さなアプリケーション(クライアントとサーバー)を作成しましたが、それらの間の「接続」(ええ、実際の接続はありません)が理由もなく頻繁に失われることがわかりました。
UDPは信頼性の低いプロトコルであることは知っていますが、ここでの問題はパケットの損失ではなく、アプリ間の通信チャネルの損失のようです。
クライアントアプリのコードは次のとおりです。
class ClientProgram
{
static void Main(string[] args)
{
var localEP = new IPEndPoint(GetIPAddress(), 0);
Socket sck = new UdpClient(localEP).Client;
sck.Connect(new IPEndPoint(IPAddress.Parse("[SERVER_IP_ADDRESS]"), 10005));
Console.WriteLine("Press any key to request a connection to the server.");
Console.ReadLine();
// This signals the server this clients wishes to receive data
SendData(sck);
while (true)
{
ReceiveData(sck);
}
}
private static void ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
int cnt = sck.Receive(buff);
long ticks = BitConverter.ToInt64(buff, 0);
Console.WriteLine(cnt + " bytes received: " + new DateTime(ticks).TimeOfDay.ToString());
}
private static void SendData(Socket sck)
{
// Just some random data
sck.Send(new byte[] { 99, 99, 99, 99 });
}
private static IPAddress GetIPAddress()
{
IPHostEntry he = Dns.GetHostEntry(Dns.GetHostName());
if (he.AddressList.Length == 0)
return null;
return he.AddressList
.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !IPAddress.IsLoopback(ip))
.FirstOrDefault();
}
}
サーバーアプリのコードは次のとおりです。
class ServerProgram
{
private static int SLEEP = 5;
static void Main(string[] args)
{
// This is a static IP address
var localEP = new IPEndPoint(GetIPAddress(), 10005);
Socket sck = new UdpClient(localEP).Client;
// When this methods returs, a client is ready to receive data
var remoteEP = ReceiveData(sck);
sck.Connect(remoteEP);
while (true)
{
SendData(sck);
System.Threading.Thread.Sleep( ServerProgram.SLEEP * 1000);
}
}
private static EndPoint ReceiveData(Socket sck)
{
byte[] buff = new byte[8];
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int cnt = sck.ReceiveFrom(buff, ref clientEP);
Console.WriteLine(cnt + " bytes received from " + clientEP.ToString());
return (IPEndPoint)clientEP;
}
private static void SendData(Socket sck)
{
DateTime n = DateTime.Now;
byte[] b = BitConverter.GetBytes(n.Ticks);
Console.WriteLine("Sending " + b.Length + " bytes : " + n.TimeOfDay.ToString());
sck.Send(b);
}
private static IPAddress GetIPAddress()
{
// Same as client app...
}
}
(これは単なるテストコードであり、無限ループやデータ検証の欠如に注意を払わないでください)
問題は、いくつかのメッセージが送信された後、クライアントがそれらの受信を停止することです。サーバーは送信を続けますが、クライアントはでスタックしsck.Receive(buff)
ます。SLEEP定数を5より大きい値に変更すると、ほとんどの場合、3つまたは4つのメッセージの後で「接続」が失われます。
Wiresharkを使用して通信を監視しているため、接続が失われたときにクライアントマシンがパケットを受信しないことを確認できます。
サーバーアプリはインターネットに直接接続されているサーバー上で実行されますが、クライアントはルーターの背後にあるローカルネットワーク内のマシンです。それらのどれもファイアウォールを実行していません。
誰かがここで何が起こっているのか手がかりを持っていますか?
ありがとうございました!
編集-追加データ:
同じネットワーク内の複数のマシンでクライアントアプリをテストしましたが、接続が常に失われます。また、他のルーターの背後にある他のネットワークでクライアントアプリをテストしましたが、問題はありません。私のルーターはLinksysRV042であり、問題は発生していません。実際、問題が発生しているのはこのアプリだけです。