TCP Socket监听仅首次可用,重启客户端后连接被拒绝求助
问题根源与修正方案
核心错误:服务器仅处理一次连接即停止监听
你的服务器代码在处理完第一个客户端的消息交互后就会退出StartServer方法,导致监听Socket被销毁,端口不再接受新连接,这是第二次客户端连接被拒绝的直接原因。
具体问题点:
- 监听Socket(
listener)被using包裹,StartServer方法执行完毕时,listener会自动被Dispose,停止监听端口。 - 代码中仅调用一次
listener.AcceptAsync()处理单个客户端,处理完成后直接返回true,没有进入下一轮监听循环。
修正步骤
1. 修改服务器代码,实现持续监听
调整服务器逻辑,让其在处理完一个客户端后继续等待下一个连接,同时调整listener的生命周期,确保服务器运行期间监听始终有效。
修正后的服务器代码示例:
public async Task StartServer() { IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("127.0.0.1"); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint ipEndPoint = new(ipAddress, 8888); Socket listener = new( ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { listener.Bind(ipEndPoint); listener.Listen(100); AddLogText("服务器已启动,等待客户端连接..."); // 持续监听新客户端连接 while (true) { Socket client = await listener.AcceptAsync(); AddLogText("新客户端已连接"); // 异步处理客户端消息,避免阻塞监听逻辑 _ = HandleClientAsync(client); } } catch (Exception ex) { AddLogText($"服务器异常: {ex.Message}"); listener.Dispose(); } } // 单独提取客户端消息处理逻辑 private async Task HandleClientAsync(Socket client) { try { while (true) { var buffer = new byte[1_024]; var received = await client.ReceiveAsync(buffer, SocketFlags.None); if (received == 0) break; // 客户端主动断开连接 var response = Encoding.UTF8.GetString(buffer, 0, received); var eom = "<|EOM|>"; if (response.IndexOf(eom) > -1) { AddLogText($"Socket server received message: \"{response.Replace(eom, "")}\""); var ackMessage = "Hallo Client!<|ACK|>"; var echoBytes = Encoding.UTF8.GetBytes(ackMessage); await client.SendAsync(echoBytes, 0); AddLogText($"Socket server sent acknowledgment: \"{ackMessage}\""); break; } } } catch (Exception ex) { AddLogText($"客户端处理异常: {ex.Message}"); } finally { client.Shutdown(SocketShutdown.Both); client.Close(); AddLogText("客户端连接已关闭"); } }
2. 客户端代码补充:显式关闭连接
客户端当前代码中using包裹的Socket会在方法结束时自动释放,但显式关闭连接能更规范地释放资源:
private async Task<bool> StartClient() { IPHostEntry ipHostInfo = await Dns.GetHostEntryAsync("127.0.0.1"); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint ipEndPoint = new(ipAddress, 8888); using Socket client = new( ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); try { await client.ConnectAsync(ipEndPoint); while (true) { var message = "Hallo Server?<|EOM|>"; var messageBytes = Encoding.UTF8.GetBytes(message); await client.SendAsync(messageBytes, SocketFlags.None); Console.WriteLine($"Socket client sent message: \"{message}\""); var buffer = new byte[1_024]; var received = await client.ReceiveAsync(buffer, SocketFlags.None); var response = Encoding.UTF8.GetString(buffer, 0, received); if (response.Contains("<|ACK|>")) { Console.WriteLine($"Socket client received acknowledgment: \"{response}\""); break; } } return true; } catch (Exception ex) { Console.WriteLine($"客户端异常: {ex.Message}"); return false; } finally { client.Shutdown(SocketShutdown.Both); client.Close(); } }
其他排查思路
- 检查端口状态:用
netstat -ano | findstr :8888命令查看端口是否被占用,确认服务器退出后端口是否正常释放。 - 确保服务器后台运行:在WPF中需用
Task.Run启动StartServer,避免主线程阻塞导致服务器进程提前结束。
内容的提问来源于stack exchange,提问作者nitg
相关产品推荐
相关产品推荐

