2016-07-04 277 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

相關問題