2016-07-04 276 views
3

我正在使用异步方法为UDP处理多个客户端的游戏创建服务器,并且我正在专门研究清除断开连接逻辑。当客户端硬故障(它们的程序没有适当的断开逻辑关闭)服务器上的readCallback抛出SocketExceptionC#UDP现有连接被远程主机强制关闭

一个现有的连接强制性地由远程主机

这是有意义的关闭,但是当下一次在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.Net.Sockets.SocketException' 在System.dll中 的System.Net.Sockets .SocketException(0x80004005):在CardCatacombs.Utilities.Networking.UDPNetworkConnection.readCallback(IAsyncResult ar)处,System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult,EndPoint & endPoint) 远程主机 强制关闭了现有连接。在C:\ Users \ ka中亚斯\桌面\实习\来源\ CardCatacombs \ CardCatacombs \工具\网络\ UDPNetworkConnection.cs:行424

抛出异常: 'System.Net.Sockets.SocketException' 在System.dll中 System.Net.Sockets.SocketException (0x80004005):现有连接被远程主机 强制关闭,位于System.Net.Sockets.Socket.DoBeginReceiveFrom(Byte []缓冲区,Int32偏移量,Int32大小,SocketFlags socketFlags,EndPoint endPointSnapshot,SocketAddress套接字地址,OverlappedAsyncResult异步结果)


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

+0

目前还不清楚其中的代码崩溃。请澄清并发布例外情况。套接字IO没有特殊的例外规则。例外总是以相同的方式工作并将被捕获。 – usr

+0

请注意,使用异步IO是没有意义的。由于你阻止了事件,你将遇到两个世界中最糟糕的情况:回调和有限的可伸缩性。使用同步IO并且不要盲目地复制错误的示例代码。 – usr

+0

看到您的编辑:您仍然需要提供例外,以明确它发生的位置。另外,“碰撞”是什么意思?我应该马上这样问。 – usr

回答

4

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 
); 
+0

非常感谢,非常奇怪,无连接协议可以“重置”。 – Blindy

相关问题