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

C# TCP聊天服务器如何监听并接受多个客户端连接

问题说明

你当前的TCP服务端仅能处理单个客户端连接,核心原因是代码仅调用一次AcceptSocket(),完成单次收发后就主动关闭连接、停止监听,无法持续接受新连接。你后续修改的版本存在逻辑嵌套、方法未调用、重复创建监听器的问题,无法正常运行。

实现多客户端持续接入的核心逻辑非常明确:

  • 启动监听器后进入无限循环,持续等待新客户端连接
  • 每接收到一个新客户端,将该客户端的通信逻辑交给独立线程/线程池处理,避免阻塞主监听循环
  • 客户端接入后第一时间发送「成功加入」的欢迎消息,再处理后续收发逻辑
  • 不要在接入第一个客户端后就停止监听器、关闭连接

修正后的代码

注意:你当前使用BackgroundWorker执行监听逻辑,不要在非UI线程直接访问WinForm控件属性,否则会触发跨线程异常。需要获取UI输入的内容(比如IP、发送文本)时,建议在启动BackgroundWorker前提前将控件值存入变量传入。

服务端代码

// 在线客户端计数,用Interlocked保证线程安全
private int connectedCount = 0;

private void Connectnattk_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        IPAddress ipAd = IPAddress.Parse(IPV4.Text);
        TcpListener server = new TcpListener(ipAd, 8001);
        server.Start();
        
        // 启动提示建议放到UI线程调用,这里简化处理
        MessageBox.Show($"服务已启动,端口8001\n本地端点:{server.LocalEndpoint}\n等待客户端连接");

        // 主监听循环:持续接受新连接,不退出
        while (true)
        {
            // 阻塞直到有新客户端接入
            TcpClient newClient = server.AcceptTcpClient();
            // 将客户端交给线程池处理,立刻回到循环等待下一个连接
            ThreadPool.QueueUserWorkItem(ProcessSingleClient, newClient);
        }
    }
    catch (Exception err)
    {
        MessageBox.Show($"服务启动异常:{err.Message}");
    }
}

/// <summary>
/// 处理单个客户端的全生命周期通信
/// </summary>
private void ProcessSingleClient(object clientObj)
{
    TcpClient client = (TcpClient)clientObj;
    try
    {
        // 在线数+1
        Interlocked.Increment(ref connectedCount);
        Console.WriteLine($"新客户端接入:{client.Client.RemoteEndPoint},当前在线:{connectedCount}");

        NetworkStream stream = client.GetStream();
        byte[] buffer = new byte[1024];
        
        // 1. 接入后立刻发送欢迎消息
        byte[] welcomeBuf = Encoding.UTF8.GetBytes("成功加入");
        stream.Write(welcomeBuf, 0, welcomeBuf.Length);

        // 2. 循环接收该客户端发来的消息,直到连接断开
        int recvLen;
        while ((recvLen = stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            string recvMsg = Encoding.UTF8.GetString(buffer, 0, recvLen);
            Console.WriteLine($"收到[{client.Client.RemoteEndPoint}]消息:{recvMsg}");
            
            // 若需要实现群聊,可在这里将消息转发给所有在线客户端
        }
    }
    catch (Exception err)
    {
        Console.WriteLine($"客户端[{client.Client.RemoteEndPoint}]异常:{err.Message}");
    }
    finally
    {
        // 连接释放逻辑
        Interlocked.Decrement(ref connectedCount);
        client.Close();
        Console.WriteLine($"客户端断开,当前在线:{connectedCount}");
    }
}

客户端适配调整

原客户端仅接收一次消息就结束,需要调整为循环接收,才能持续收到服务端消息:

TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(RecieveIPAdd.Text, 8001);
MessageBox.Show("已连接服务器");
Stream stm = tcpclnt.GetStream();

byte[] recvBuf = new byte[1024];
int recvLen;
// 持续接收消息
while ((recvLen = stm.Read(recvBuf, 0, recvBuf.Length)) > 0)
{
    string msg = Encoding.UTF8.GetString(recvBuf, 0, recvLen);
    // 第一条消息为「成功加入」的欢迎提示
    Console.WriteLine($"收到消息:{msg}");
}

你之前修改版本的具体问题
  • 定义了ServerStart()方法但从未调用,多客户端监听逻辑完全没有执行
  • 重复创建两个绑定8001端口的TcpListener实例,第二个实例启动时会直接抛出端口占用异常
  • HandleConnection方法内部再次调用AcceptSocket(),等于在处理已接入客户端的线程里又阻塞等待新连接,逻辑完全错误
  • 接入第一个客户端后就执行s.Close()、myList.Stop(),直接关闭连接和监听器,无法持续服务
  • 所有逻辑跑在单一线程,处理客户端收发时会阻塞监听流程,无法接受新连接

内容的提问来源于stack exchange,提问作者Theoneguy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:27:37