You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:27:32