C# UDP 现有连接被远程主机强行关闭

标签 c# network-programming udp

我正在为一个游戏创建一个服务器,该服务器使用异步方法通过 UDP 处理多个客户端,并且专门致力于干净的断开连接逻辑。当客户端硬崩溃时(他们的程序在没有适当的断开连接逻辑的情况下关闭)服务器上的 readCallback 抛出 SocketException

An existing connection was forcibly closed by the remote host

这是有道理的,但是当下次在 read 的循环中触发读取时,尽管在回调中处理了异常,它还是崩溃了。

    private void connectedState()
    {
        while (connected)
        {
            //reset the trigger to non-signaled
            readDone.Reset();

            read(socket);

            //block on reading data
            readDone.WaitOne();
        }
    }


    private void read(Socket sock)
    {
        // Creates an IpEndPoint to capture the identity of the sending host.
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        EndPoint senderRemote = sender;

        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = sock;

        //crashes after an exception is caught within the callback
        sock.BeginReceiveFrom(state.buffer, 0, StateObject.MESSAGE_SIZE, SocketFlags.None, ref senderRemote, new AsyncCallback(readCallback), state);
    }


    private void readCallback(IAsyncResult ar)
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket sock = state.workSocket;

        EndPoint senderRemote = new IPEndPoint(IPAddress.Any, 0);

        try
        {
            // Read data from the client socket. 
            int bytesRead = sock.EndReceiveFrom(ar, ref senderRemote);

            if (bytesRead <= 0)
            {
                //handle disconnect logic
            }
            else
            {
                //handle the message received
            }
        }
        catch (SocketException se)
        {
            Console.WriteLine(se.ToString());
        }

        // Signal the read thread to continue
        readDone.Set();
    }

抛出了两个异常,我相信其中一个被捕获了:


抛出异常:System.dll 中的“System.Net.Sockets.SocketException” System.Net.Sockets.SocketException (0x80004005): 现有连接被远程主机强行关闭 在 System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult,EndPoint&endPoint) 在 CardCatacombs.Utilities.Networking.UDPNetworkConnection.readCallback(IAsyncResult ar) 在 C:\Users\kayas\Desktop\Practicum\Source\CardCatacombs\CardCatacombs\Utilities\Networking\UDPNetworkConnection.cs:line 424

抛出异常:System.dll 中的“System.Net.Sockets.SocketException” System.Net.Sockets.SocketException (0x80004005): 现有连接被远程主机强行关闭 在 System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte[] 缓冲区,Int32 偏移量,Int32 大小,SocketFlags socketFlags,EndPoint endPointSnapshot,SocketAddress socketAddress,OverlappedAsyncResult asyncResult)


我希望能够干净地处理客户端崩溃并继续运行,因为还有其他客户端连接到服务器。

最佳答案

来自 this forum thread ,似乎UDP套接字也在接收ICMP消息并在接收时抛出异常。如果端口不再监听(在硬崩溃之后),ICMP 消息会导致“强制关闭”异常。

如果不需要,可以在创建 UdpClient 时使用以下代码禁用此异常,如上文所述:

public const int SIO_UDP_CONNRESET = -1744830452;
var client = new UdpClient(endpoint);
client.Client.IOControl(
    (IOControlCode)SIO_UDP_CONNRESET, 
    new byte[] { 0, 0, 0, 0 }, 
    null
);

对于dotnet core用户,由于这个“Socket.IOControl”是Windows特有的控制代码,不支持其他平台,我们会得到以下异常:

Unhandled exception. System.PlatformNotSupportedException: Socket.IOControl handles Windows-specific control codes and is not supported on this platform.

为了更好的兼容性,我们应该检查当前的平台:

using System.Runtime.InterosServices;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
   //...
}

关于C# UDP 现有连接被远程主机强行关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38191968/

相关文章:

c# - Angular 2 - 将来自 Web Api 的 byte[] 呈现为图像源

c++ - 如何检查发送到特定端口上的 IP 地址的数据?

iphone - iOS 4 后台模式下的 NSTimer 或 NSThread

c++ - 我可以将 UDP 包广播到网络的一部分吗?

c++ - 使用 boost::asio 创建异步 UDP 客户端

c# - 如何在 Azure Functions 中使用 Http 触发器进行模型绑定(bind)?

c# - VS2019 Roslyn编译器通用约束方法解析

c# - MVVM – 模型的正确实现

c - free( ) 导致 malloc_error_break

java - 我能否唤醒因调用 DatagramSocket.receive() 而阻塞的线程?