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
相关产品推荐
相关产品推荐

