在 UDP 服务器中接收数据包时重置连接
本文关键字:连接 数据包 UDP 服务器 | 更新日期: 2023-09-27 18:32:29
我正在开发一个服务器应用程序(C#,.NET 4.0),该应用程序每秒需要处理数千个UDP数据包。所以我决定SocketAsyncEventArg
来实现服务器。
面临的问题是我的实现只收到一个数据包,然后我收到"连接重置"错误(我从没想过我会得到这个错误,因为 UDP 是无连接的)。这是我的测试实现:
using System;
using System.Net;
using System.Net.Sockets;
static class Program
{
static void Main(string[] args)
{
UdpEchoServer.Start();
while (true)
{
Console.ReadLine();
SendPacket();
}
}
static void SendPacket()
{
Console.WriteLine("SendPacket");
var c = new UdpClient();
c.Send(new byte[5], 5, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 445));
c.Close();
}
}
static class UdpEchoServer
{
static Socket mSocket;
static byte[] mBuffer;
static SocketAsyncEventArgs mRxArgs, mTxArgs;
static IPEndPoint mAnyEndPoint, mLocalEndPoint;
public static void Start()
{
mAnyEndPoint = new IPEndPoint(IPAddress.Any, 0);
mLocalEndPoint = new IPEndPoint(IPAddress.Any, 445);
mBuffer = new byte[1024];
mRxArgs = new SocketAsyncEventArgs();
mTxArgs = new SocketAsyncEventArgs();
mRxArgs.Completed += ReceiveComplete;
mTxArgs.Completed += SendComplete;
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
mSocket.Bind(mLocalEndPoint);
ReceiveNext();
}
static void ReceiveNext()
{
Console.WriteLine("ReceiveNext");
mRxArgs.RemoteEndPoint = mAnyEndPoint;
mRxArgs.SetBuffer(mBuffer, 0, mBuffer.Length);
if (!mSocket.ReceiveFromAsync(mRxArgs))
Console.WriteLine("Error in ReceiveNext: " + mRxArgs.SocketError);
}
static void ReceiveComplete(object sender, SocketAsyncEventArgs e)
{
Console.WriteLine("Receive Complete: " + mRxArgs.SocketError);
if (mRxArgs.SocketError != SocketError.Success)
return;
mTxArgs.SetBuffer(mBuffer, 0, mRxArgs.BytesTransferred);
mTxArgs.RemoteEndPoint = mRxArgs.RemoteEndPoint;
Console.WriteLine("Sending reply packet");
if (!mSocket.SendToAsync(mTxArgs))
Console.WriteLine("Error in ReceiveComplete: " + mRxArgs.SocketError);
}
static void SendComplete(object sender, SocketAsyncEventArgs e)
{
Console.WriteLine("Send Complete: " + mTxArgs.SocketError);
if (mTxArgs.SocketError != SocketError.Success)
return;
ReceiveNext();
}
}
很抱歉代码很长,但它真的很简单。我等待一个数据包,回复远程端点,然后等待下一个数据包。这是输出:
ReceiveNext
SendPacket
Receive Complete: Success
Sending reply packet
Send Complete: Success
ReceiveNext
Error in ReceiveNext: ConnectionReset
请您建议上面的代码片段中有什么问题吗?
UDP 套接字会发生这种情况。您需要做的就是在绑定之前更改套接字操作模式。在 Start
方法中使用此代码。
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
const int SIO_UDP_CONNRESET = -1744830452;
byte[] inValue = new byte[] {0};
byte[] outValue = new byte[] {0};
mSocket.IOControl(SIO_UDP_CONNRESET, inValue, outValue);
mSocket.Bind(mLocalEndPoint);
如果您删除或注释掉对UdpClient
Close
的调用,则程序将按预期工作。为什么会发生这种情况我不确定,但这可能与 Windows 环回网络有关。