C# TCP聊天室服务端因客户端断开导致Socket.Receive崩溃的问题解决
解决服务端客户端断开时触发SocketException的问题
这个问题我做聊天室项目时也碰到过,核心原因是当客户端主动断开或者网络异常中断时,socket.Receive()尝试读取已经失效的连接,而你的代码没做异常处理,直接导致程序崩溃。另外我还注意到代码里有个小bug——解码字符串时用了未定义的变量b,咱们一起把这些问题解决掉:
修改后的服务端代码
Socket _server; private void StartServer() { _server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 100010)); _server.Listen(1); while (true) { Socket client = _server.Accept(); Thread rd = new Thread(ReceiveData); rd.Start(client); } } public void ReceiveData(object skt) { Socket socket = (Socket)skt; try { while (true) { byte[] buffer = new byte[1024]; int r = socket.Receive(buffer); // 返回值为0时,说明客户端正常关闭了连接 if (r == 0) { Console.WriteLine($"客户端 {socket.RemoteEndPoint} 正常断开连接"); break; } // 正确解码收到的字节(只取实际收到的r个字节,避免乱码) string message = Encoding.Unicode.GetString(buffer, 0, r); Console.WriteLine($"{socket.RemoteEndPoint}: {message}"); } } catch (SocketException ex) { // 错误码10054对应「远程主机强迫关闭连接」的场景 if (ex.SocketErrorCode == SocketError.ConnectionReset) { Console.WriteLine($"客户端 {socket.RemoteEndPoint} 异常断开连接"); } else { Console.WriteLine($"Socket错误: {ex.Message}"); } } catch (Exception ex) { // 兜底捕获其他异常,避免单个客户端的问题导致服务端崩溃 Console.WriteLine($"未知错误: {ex.Message}"); } finally { // 无论正常退出还是异常退出,都要关闭Socket释放资源 if (socket.Connected) { socket.Shutdown(SocketShutdown.Both); } socket.Close(); Console.WriteLine($"已清理客户端 {socket.RemoteEndPoint} 的连接资源"); } }
关键修复点说明
- 异常捕获:用
try-catch包裹接收循环,专门处理SocketException,区分正常断开和异常断开的场景,避免程序直接崩溃。 - 处理返回值0:TCP协议规范中,客户端正常关闭连接时,
Receive()会返回0而不是抛出异常,必须处理这种情况。 - 修复字符串解码:替换了未定义的
b变量,并且限制只解码实际收到的r个字节,避免出现乱码。 - 资源清理:在
finally块中统一关闭Socket,确保无论是否发生异常,都能及时释放连接资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

