如何处理客户端断开在套接字编程
本文关键字:断开 套接字 编程 客户端 何处理 处理 | 更新日期: 2023-09-27 17:51:22
我使用套接字写了一个服务器端代码,它工作得很好,但有一个问题我不知道如何处理这种情况:如果客户端只是关闭应用程序而不发送断开请求,我的服务器端程序崩溃。我需要做些什么来避免这种情况?请指导我,我是新的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);
}
}
您的应用程序崩溃了,因为您在方法的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;
}
}
}
您在catch
块内抛出了一个新的异常,除非您正在做一些日志记录或类似的事情,否则这没有多大意义。将catch块更改为:
catch(SocketException)
{
}
另外,您应该检查从EndReceive
读取返回的字节数。如果接收到零字节,则表示客户端已关闭连接:
int numReceived = clientSocket.EndReceive(result);
if(numReceived == 0)
{
//client has shutdown the connection
}