c# - 在 UDP 服务器中接收数据包时连接重置

标签 c# .net sockets asynchronous

我正在开发一个每秒需要处理数千个 UDP 数据包的服务器应用程序(C#、.NET 4.0)。所以我决定用 SocketAsyncEventArg 来实现服务器。

我面临的问题是我的实现只收到一个数据包,然后出现“ConnectionReset”错误(我从没想过我会收到此错误,因为 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 套接字会发生这种情况。您需要做的就是更改 socket operating mode在绑定(bind)它之前。在您的 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);

关于c# - 在 UDP 服务器中接收数据包时连接重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10332630/

相关文章:

c# - 平面文件目标 预执行阶段失败。无法打开数据文件

c# - 有可能 signalR 客户端网络连接另一台 PC 上的服务器吗?

c# - 声明具有属性的类并同时填充这些属性的最佳方法是什么

.net - 如何通过类型名称获取泛型接口(interface)的类型?

c# - 在 C# 中使用编码从 C 获取字符串数组

C 获取监听服务器的 IP

C++ Socket recv 接收不到正确的字节数?

c# - 调试时无法评估表达式

远程连接消失后,PHP stream_select 继续触发空白读取事件

c# - 如何获取窗口类名的长度,以便知道要分配多大的缓冲区?