Java UDP Socket异常:socket.receive()仅首次阻塞后续无阻塞问题问询
UDP Socket的receive()后续迭代不阻塞?这绝对不正常!
这肯定是代码逻辑和DatagramPacket的使用方式出问题了,咱们来唠清楚:
首先明确:正常情况下,DatagramSocket.receive()每次调用都会阻塞,直到有新的UDP数据报到达。如果你的代码里后续调用不阻塞,绝对是有地方用错了。
问题出在哪?
看你的代码,核心有两个问题:
1. 复用DatagramPacket时没重置缓冲区长度
你应该是复用了同一个request对象(虽然代码里没显示初始化,但肯定是提前创建的)。当第一次调用receive(request)时,这个对象的有效长度(通过getLength()获取)会被设置为收到的数据的实际长度。如果后续调用receive()前没有把长度重置回缓冲区的初始总长度,那么哪怕没有新的数据报到达,receive()也会直接认为缓冲区里还有“旧数据”可以返回,不会阻塞。
2. 循环逻辑顺序搞反了
你的循环条件是while((input=fileIn.readline()))!=null——这意味着只要文件还有行可读,就会进入循环体。第一次阻塞收到请求后,你发了一行;然后循环继续,先读下一行文件内容,再调用receive()。这时候如果receive()因为上面的原因没阻塞,就会直接发送下一行,导致瞬间把整个文件的内容都发完,完全跳过了等待客户端请求的步骤。
怎么修复?
调整循环逻辑+每次接收前重置DatagramPacket的长度:
String input; DatagramSocket socket = new DatagramSocket(port); // 初始化请求包,用固定大小的缓冲区 byte[] requestBuffer = new byte[1024]; DatagramPacket request = new DatagramPacket(requestBuffer, requestBuffer.length); while (true) { // 关键:每次接收前重置请求包的长度,确保receive()会阻塞等待新数据 request.setLength(requestBuffer.length); socket.receive(request); // 先等请求,再读文件行——顺序反过来! input = fileIn.readLine(); if (input == null) { // 文件读完了,退出循环 break; } // 构造并发送响应 byte[] responseData = input.getBytes(); DatagramPacket response = new DatagramPacket( responseData, responseData.length, request.getAddress(), request.getPort() ); socket.send(response); } // 别忘了关闭资源 socket.close(); fileIn.close();
总结
- 你的情况完全不正常,正常的
receive()每次都应该阻塞到新数据到达 - 罪魁祸首是
DatagramPacket的长度没有重置,导致后续调用直接返回旧数据 - 循环顺序错误放大了这个问题,让程序一次性发完所有文件内容
内容的提问来源于stack exchange,提问作者avermaet
相关产品推荐
相关产品推荐

