无法从单个TCP端口向TCP监听服务发送多条消息的问题求助
问题排查与修复方案
以下是你代码中存在的核心问题及对应的修复方案:
- 端口逻辑完全写反:你的需求是客户端向7022端口的监听服务发消息,那目标服务地址(remoteEP)的端口应该是7022,你要求客户端从7021端口发送的话,本地绑定的端口才应该是7021。你当前代码把两个端口写反,会导致实际尝试连接7021端口的服务,且客户端自身占用7022端口,如果你的监听服务已经在使用7022端口,会直接报端口占用错误。
- 客户端不必要的端口绑定:TCP客户端默认不需要手动调用
Bind方法指定本地端口,操作系统会自动分配可用端口,只有你明确要求客户端必须从指定端口发请求时才需要手动绑定。 - 缺少TCP粘包处理逻辑:TCP是面向流的传输协议,没有天然的消息边界,你连续发送多条消息时,接收端很可能会把多条消息合并成一次读取结果返回,需要自己约定消息边界(比如固定长度、特殊分隔符、消息头带长度字段),否则接收端无法正确拆分消息。
- 基础校验缺失:没有判断
Send方法的返回值是否等于待发送消息的总长度,极端网络环境下可能出现部分发送的情况,导致接收端拿到不完整的消息;同时没有异常捕获逻辑,连接失败、发送中断等问题无法直观定位。 - 监听地址匹配问题:如果你的7022端口监听服务是绑定在127.0.0.1或者其他网卡IP上,用192.168.0.126连接可能会出现连接拒绝错误,需要确认监听服务的绑定地址。
修正后参考代码
string message = "787814014E612096"; // 目标监听服务的地址+端口,此处为7022 IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("192.168.0.126"), 7022); Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // 如果确实要求客户端必须从7021端口发送,再打开下面两行Bind逻辑,否则可以直接删除 // IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("192.168.0.126"), 7021); // sender.Bind(localEP); sender.Connect(remoteEP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); byte[] msgBuffer = Encoding.ASCII.GetBytes(message); for (int index = 1; index < 6; index++) { Console.WriteLine("Send packet: " + index); int totalSent = 0; // 循环发送确保所有字节都成功发出 while (totalSent < msgBuffer.Length) { int sent = sender.Send(msgBuffer, totalSent, msgBuffer.Length - totalSent, SocketFlags.None); if (sent == 0) { throw new Exception("连接已断开,发送失败"); } totalSent += sent; } Thread.Sleep(2000); } } catch (Exception ex) { Console.WriteLine("操作出错:" + ex.Message); } finally { if (sender.Connected) { sender.Shutdown(SocketShutdown.Both); } sender.Close(); sender.Dispose(); }
调试建议
- 先启动7022端口的监听服务,再启动客户端程序,避免连接拒绝错误
- 可以先用telnet或者nc工具测试7022端口是否能正常连通,排除网络、防火墙拦截问题
- 接收端一定要做粘包拆分处理,否则即使客户端发送正常,接收端也可能拿到合并后的消息
内容的提问来源于stack exchange,提问作者Salman Elahi
相关产品推荐
相关产品推荐

