本地DatagramSocket服务端向自身发送报文引发死循环如何解决?
问题根因
你的死循环问题核心是UDP回包时端口使用错误,具体问题点如下:
- UDP是无连接协议,客户端通过
new DatagramSocket()无参构造创建socket时,系统会随机分配一个动态端口作为客户端的源端口,而非你传入的服务端监听端口 - 你在服务端的
sendMessage方法中硬编码使用类内部存储的port属性,这个属性存储的是服务端自身的监听端口,回包时用该端口+本地地址,报文就会直接发送给服务端自己的socket,触发接收逻辑后再次回包,最终形成死循环 - 冗余代码问题:客户端接收报文时给
DatagramPacket指定目标地址和端口属于无效操作,receive()方法会自动填充收到报文的源地址、源端口和数据
修复方案
1. 优先新增服务端专用回包方法
直接复用收到的客户端报文的地址和端口回包,避免手动传参出错:
// 在Server类中新增回包方法 public void replyMessage(DatagramPacket receivedPacket, String message) { byte[] messageBytes = message.getBytes(); DatagramPacket replyPacket = new DatagramPacket( messageBytes, messageBytes.length, receivedPacket.getAddress(), receivedPacket.getPort() ); sendPacket(replyPacket); }
后续在服务端的PacketReceiver回调中需要回包时,直接调用该方法传入收到的报文对象即可,不要使用原sendMessage方法。
2. 通用方法修复
如果需要保留sendMessage方法的通用性,修改ICommunicator接口的方法签名,增加端口参数,不再硬编码使用内部存储的端口:
// 客户端、服务端同步修改sendMessage方法 @Override public void sendMessage(InetAddress inetAddress, int port, String message) { byte[] messageBytes = message.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port); sendPacket(datagramPacket); }
- 客户端发往服务端时,传入服务端的监听端口即可
- 服务端回发客户端时,传入
receivedPacket.getPort()获取到的客户端动态端口即可
内容的提问来源于stack exchange,提问作者Seby_Plays
相关产品推荐
相关产品推荐

