2013-01-12 114 views
0

我一直在使用套接字编写服务器端的代码,它工作正常,但有一个问题,我不知道如何处理这种情况:如果客户只是关闭应用程序而不发送断开连接请求时,我的服务器端程序崩溃。我需要做什么来避免这种情况?请指导我我是Socket编程的新手。如何在Socket编程中处理客户端断开连接?

private void OnReceive(IAsyncResult result) 
{ 
    try 
    { 
     Socket clientSocket = (Socket)result.AsyncState; 
     clientSocket.EndReceive(result); 

     command = responseMessage = string.Empty; 
     command = ByteToString(receviedData); 
     receviedData = new byte[30]; 

     if (command=="Connect") 
     { 
      ClientInfo clientInfo = new ClientInfo(); 
      clientInfo.socket = clientSocket; 
      clientInfo.IP = clientSocket.RemoteEndPoint.ToString(); 
      connectedClients.Add(clientInfo); 
      responseMessage = "Connection established..."; 
     } 
     else if (command=="Disconnect") 
     { 
      for (int i = 0; i < connectedClients.Count; i++) 
      { 
       if (connectedClients[i].socket == clientSocket) 
       { 
        connectedClients.RemoveAt(i); 
        break; 
       } 
      } 
      clientSocket.Close(); 
     } 
     else 
     { 
      responseMessage = "Error"; 
     } 

     byte[] responseStatus = StringToByte(responseMessage); 
     for (int i = 0; i < connectedClients.Count; i++) 
     { 
      if (connectedClients[i].socket==clientSocket) 
      { 
       connectedClients[i].socket.BeginSend(responseStatus, 0, responseStatus.Length,SocketFlags.None, new AsyncCallback(OnSend), connectedClients[i].socket); 
       break; 
      } 
     } 

    } 
    catch(Exception ex) 
    { 
     throw new Exception(ex.Message); 
    } 
} 
+0

你需要的try/catch相应的异常:http://msdn.microsoft.com/en-US/library/0yd65esw( v = vs.110).aspx 由于您似乎是堆栈溢出的新手,请务必阅读FAQ部分。 http://stackoverflow.com/faq – yas4891

+0

请发布您的例外代码。 –

+0

我使用的这个,但整个服务器端的应用程序,因为这崩溃,没能以及 – user1941098

回答

2

您的应用程序崩溃,因为您在方法的catch块中抛出异常。

如果您不希望应用程序崩溃,则需要从catch块中删除throw new Exception(ex.Message);行。 将其替换为处理该错误的代码并正常地将应用程序恢复到安全状态。从阅读你的代码,这应该由connectedClients

其次去除clientSocket来完成,最好是只使用throw;代替throw new Exception(ex.Message);throw;将重新抛出原始异常对象,从而保留堆栈跟踪和其他重要信息,这些信息有助于调试软件。 使用new Exception("Message")将使用当前堆栈跟踪创建一个全新的异常对象。

private void OnReceive(IAsyncResult result) 
{ 
    try 
    { 
     Socket clientSocket = (Socket)result.AsyncState; 
     clientSocket.EndReceive(result); 

     command = responseMessage = string.Empty; 
     command = ByteToString(receviedData); 
     receviedData = new byte[30]; 

     if (command=="Connect") 
     { 
      ClientInfo clientInfo = new ClientInfo() { 
       socket = clientSocket, 
       IP = clientSocket.RemoteEndPoint.ToString(), 
       }; 
      connectedClients.Add(clientInfo); 
      responseMessage = "Connection established..."; 
     } 
     else if (command=="Disconnect") 
     { 
      removeClientInfo(clientSocket); 
      clientSocket.Close(); 
     } 
     else 
     { 
      responseMessage = "Error"; 
     } 

     byte[] responseStatus = StringToByte(responseMessage); 
     for (int i = 0; i < connectedClients.Count; i++) 
     { 
      if (connectedClients[i].socket==clientSocket) 
      { 
       connectedClients[i].socket.BeginSend(responseStatus, 0, responseStatus.Length,SocketFlags.None, new AsyncCallback(OnSend), connectedClients[i].socket); 
       break; 
      } 
     } 

    } 
    catch(Exception ex) 
    { 
     // add error handling and gracefully recover 
     // caution: The way done here, might work, but it smells :-/ 
     removeClientInfo((Socket)result.AsyncState); 
     ((Socket)result.AsyncState).Close(); 
    } 
} 

/// removes the client info from the connectedClients enumerable 
private void removeClientInfo(Socket socket) 
{ 
    for (int i = 0; i < connectedClients.Count; i++) 
    { 
     if (connectedClients[i].socket == socket) 
     { 
      connectedClients.RemoveAt(i); 
      break; 
     } 
    } 
} 
+0

有没有更好的方法呢?任何最佳实践来处理? – user1941098

+0

我指的是我的答案的哪一部分?恕我直言,两部分都是*最佳做法*。 – yas4891

+0

clientSocket不在catch块的范围内!我如何处理移除或关闭Catch块中客户端的连接? – user1941098

1

您的catch块,除非你正在做一些记录或类似的不多大意义内抛出一个新的异常。像更改catch块:

catch(SocketException) 
{ 
} 

此外,你应该检查从EndReceive返回读取的字节数。如果您收到零个字节,这意味着客户端已关闭连接:

int numReceived = clientSocket.EndReceive(result); 
if(numReceived == 0) 
{ 
    //client has shutdown the connection 
} 
+0

EndReceive和Receive方法有什么区别吗? – user1941098

+1

当然他们是不同的。它们分别与异步套接字和同步套接字相关。 –

相关问题