c# Udp BeginReceive - 消息乱序
c# Udp BeginReceive - Messages out of order
我目前正在尝试创建 UDP client/server。这很简单,有一个发送函数,它发送一个字节,然后客户端立即响应一条包含我监听的信息的消息
我一直无法接收数据。我一直在接收数据,收到的包裹确实有正确的长度,但是消息似乎乱序了。
SendAndReceive 函数在 10 秒计时器上。
编辑:如果我每次调用 SendAndReceive 函数时都重新创建 MyUdpClient,它会工作并且包的顺序没有错误。
这是我的代码:
private void SendAndReceive(object sender = null, ElapsedEventArgs e = null)
{
ClientEndpoint = new IPEndPoint(IPAddress.Parse(IP), Port);
// Works if i recreate MyUdpClient...
MyUdpClient = new UdpClient();
MyUdpClient.ExclusiveAddressUse = false;
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
MyUdpClient.Send(InfoPacket, InfoPacket.Length, ClientEndpoint);
try
{
MyUdpClient.BeginReceive(new AsyncCallback(ReceiveMessages), null);
}
catch (Exception exception)
{
Console.WriteLine($"Exception: {exception.ToString()}");
}
}
public void ReceiveMessages(IAsyncResult res)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, Port);
byte[] receivedPacket = MyUdpClient.EndReceive(res, ref RemoteIpEndPoint);
var ipAddress = RemoteIpEndPoint.Address.ToString();
MyUdpClient.BeginReceive(new AsyncCallback(ReceiveMessages), null);
// This is for debugging.
string receivedTime = DateTime.Now.ToString("HH:mm:ss");
Console.WriteLine($"[{receivedTime}]{ipAddress} {receivedPacket.Length} {Encoding.Default.GetString(receivedPacket)}");
// Process Data Further
...
}
常见的输出通常是这样的:
[18.29.30]172.20.55.32 475 a
[18.29.30]172.20.55.10 455 b
[18.29.30]172.20.55.101 440 c
[18.29.30]172.20.55.17 452 d
[18.29.30]172.20.55.31 414 e
[18.29.30]172.20.55.20 449 f
[18.29.30]172.20.55.8 456 g
[18.29.30]172.20.55.28 381 h
...
[18.29.40]172.20.55.32 475 a
[18.29.40]172.20.55.10 455 b
[18.29.40]172.20.55.101 440 c
[18.29.40]172.20.55.17 452 d
[18.29.40]172.20.55.31 414 c <-- (gets cut down to 414 bytes)
[18.29.40]172.20.55.20 449 f
[18.29.40]172.20.55.8 456 g
[18.29.40]172.20.55.28 381 h
字母代表解码后的信息。第一次收到这些消息时,它们是正确的,但是之后,消息就变得混乱了。
有什么想法吗?我不确定该往哪个方向走。是线程问题还是我必须稍后解码收到的包?
感谢任何帮助and/or指导
-安德烈
我更改了我的整个实现以在 Task
中使用 .Receive
而不是 .BeginReceive
。我发现使用 Task
更好,因为我需要安全地停止和启动接收功能,它解决了我遇到的奇怪问题。
我目前正在尝试创建 UDP client/server。这很简单,有一个发送函数,它发送一个字节,然后客户端立即响应一条包含我监听的信息的消息
我一直无法接收数据。我一直在接收数据,收到的包裹确实有正确的长度,但是消息似乎乱序了。
SendAndReceive 函数在 10 秒计时器上。
编辑:如果我每次调用 SendAndReceive 函数时都重新创建 MyUdpClient,它会工作并且包的顺序没有错误。
这是我的代码:
private void SendAndReceive(object sender = null, ElapsedEventArgs e = null)
{
ClientEndpoint = new IPEndPoint(IPAddress.Parse(IP), Port);
// Works if i recreate MyUdpClient...
MyUdpClient = new UdpClient();
MyUdpClient.ExclusiveAddressUse = false;
MyUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
MyUdpClient.Send(InfoPacket, InfoPacket.Length, ClientEndpoint);
try
{
MyUdpClient.BeginReceive(new AsyncCallback(ReceiveMessages), null);
}
catch (Exception exception)
{
Console.WriteLine($"Exception: {exception.ToString()}");
}
}
public void ReceiveMessages(IAsyncResult res)
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, Port);
byte[] receivedPacket = MyUdpClient.EndReceive(res, ref RemoteIpEndPoint);
var ipAddress = RemoteIpEndPoint.Address.ToString();
MyUdpClient.BeginReceive(new AsyncCallback(ReceiveMessages), null);
// This is for debugging.
string receivedTime = DateTime.Now.ToString("HH:mm:ss");
Console.WriteLine($"[{receivedTime}]{ipAddress} {receivedPacket.Length} {Encoding.Default.GetString(receivedPacket)}");
// Process Data Further
...
}
常见的输出通常是这样的:
[18.29.30]172.20.55.32 475 a
[18.29.30]172.20.55.10 455 b
[18.29.30]172.20.55.101 440 c
[18.29.30]172.20.55.17 452 d
[18.29.30]172.20.55.31 414 e
[18.29.30]172.20.55.20 449 f
[18.29.30]172.20.55.8 456 g
[18.29.30]172.20.55.28 381 h
...
[18.29.40]172.20.55.32 475 a
[18.29.40]172.20.55.10 455 b
[18.29.40]172.20.55.101 440 c
[18.29.40]172.20.55.17 452 d
[18.29.40]172.20.55.31 414 c <-- (gets cut down to 414 bytes)
[18.29.40]172.20.55.20 449 f
[18.29.40]172.20.55.8 456 g
[18.29.40]172.20.55.28 381 h
字母代表解码后的信息。第一次收到这些消息时,它们是正确的,但是之后,消息就变得混乱了。
有什么想法吗?我不确定该往哪个方向走。是线程问题还是我必须稍后解码收到的包?
感谢任何帮助and/or指导
-安德烈
我更改了我的整个实现以在 Task
中使用 .Receive
而不是 .BeginReceive
。我发现使用 Task
更好,因为我需要安全地停止和启动接收功能,它解决了我遇到的奇怪问题。