这是我的第一个问题,我不是英语母语人士,所以我的英语可能有些不准确。
我正在实现实时网络引擎,并使用Socket.xxxAsync()方法。
我在服务器端创建了一个UDP套接字,如下所示:
m_udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_udpSock.Bind(new IPEndPoint(IPAddress.Any, udpPort));
SocketAsyncEventArgs udpRecvArg = new SocketAsyncEventArgs();
udpRecvLoopStart(m_udpSock, udpRecvArg);
(客户端已知udpPort。)
private void udpRecvLoopStart(Socket udpSocket, SocketAsyncEventArgs udpRecvArg)
{
udpRecvArg.AcceptSocket = udpSocket;
byte[] udpRecvBuffer = new byte[NetworkEngineConst.MsgSizeMax];
udpRecvArg.SetBuffer(udpRecvBuffer, 0, udpRecvBuffer.Length);
udpRecvArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
udpRecvArg.Completed += new EventHandler<SocketAsyncEventArgs>(udpRecvArg_Completed);
udpRecv(udpRecvArg);
}
private void udpRecv(SocketAsyncEventArgs udpRecvArg)
{
bool synchronous = false;
try
{
synchronous = !udpRecvArg.AcceptSocket.ReceiveFromAsync(udpRecvArg);
}
catch (Exception e)
{
OnIOError("recvUdp()\n" + e.ToString());
return;
}
if (synchronous)
udpRecvArg_Completed(this, udpRecvArg);
}
完成事件处理程序如下:
void udpRecvArg_Completed(object sender, SocketAsyncEventArgs udpRecvArg)
{
EndPoint udpEp = udpRecvArg.RemoteEndPoint;
string msg = Encoding.UTF8.GetString(udpRecvArg.Buffer, 14, udpRecvArg.BytesTransferred - 14);
Debug.WriteLine(udpEp + " " + msg);
udpRecv(udpRecvArg);
}
(前14个字节是消息前缀、CRC和序列号)
两个(或多个)客户端向服务器发送UDP数据包。(发送速率每秒数百个)
例如,客户端1(192.168.0.1:50113)发送“11111111111111111111111111111”,客户端2(192.168.0.1:59368)发送“2”。
但有时(并不总是),终点地址是错误的。日志如下:
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:59368 2
192.168.0.1:59368 2
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:59368 11111111111111111111111111111 <- 错误部分
192.168.0.1:59368 2
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:59368 2
192.168.0.1:50113 11111111111111111111111111111
192.168.0.1:59368 2
192.168.0.1:59368 2
我怀疑是数据包错误,但是数据包没有错误(我用Wireshark确认过)。
这是一个bug吗?
(补充)
我尝试了
m_udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_udpSock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
m_udpSock.Bind(new IPEndPoint(IPAddress.Any, udpPort));
并替换了ReceiveFromAsync()为ReceiveMessageFromAsync()。
但是SocketAsyncEventArgs.ReceiveMessageFromPacketInfo.Address为空。
(附加) ReceiveMessageFromAsync()的问题是一个bug。
它已经在.NET Framework 4.0中修复。 这里 谢谢。