Java UDP客户端-服务器程序响应内容被截断问题求助
问题根源
客户端复用了同一个DatagramPacket对象进行发送和接收,并且在发送时通过packet.setData(bobInput.getBytes())将数据包的内部缓冲区替换为了长度仅为3的字节数组(对应输入"Bob"的长度)。当后续调用socket.receive(packet)时,该数据包只能容纳3字节的数据,因此服务器发送的完整回复"Hello Bob!"被截断为前3字节"Hel"。
另外,你的服务器代码中缺少发送回复的socket.send(packet)语句,这应该是粘贴代码时的遗漏(否则客户端无法收到任何数据)。
修复方案
方案1:客户端分别创建发送和接收用的数据包
避免复用同一个DatagramPacket,创建两个独立的数据包分别处理发送和接收:
public class Client { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(); socket.setSoTimeout(5000); Scanner input = new Scanner(System.in); System.out.print("Please enter a message to send to Alice: "); String bobInput = input.nextLine(); input.close(); // 发送用数据包,使用输入内容的字节数组 byte[] sendBuffer = bobInput.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, InetAddress.getByName("localhost"), 1500); socket.send(sendPacket); // 接收用数据包,使用足够大的缓冲区 byte[] receiveBuffer = new byte[65535]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); socket.receive(receivePacket); System.out.println("Received from Alice: " + new String(receivePacket.getData(), 0, receivePacket.getLength())); socket.close(); } }
方案2:客户端复用数据包,但重置缓冲区和长度
如果坚持复用同一个DatagramPacket,需要在发送后重置缓冲区的长度,确保能容纳完整的回复:
public class Client { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(); socket.setSoTimeout(5000); Scanner input = new Scanner(System.in); System.out.print("Please enter a message to send to Alice: "); String bobInput = input.nextLine(); input.close(); byte[] buffer = new byte[65535]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 1500); // 填充发送数据并设置有效长度 byte[] sendData = bobInput.getBytes(); System.arraycopy(sendData, 0, buffer, 0, sendData.length); packet.setLength(sendData.length); socket.send(packet); // 重置数据包长度为缓冲区总大小,准备接收完整回复 packet.setLength(buffer.length); socket.receive(packet); System.out.println("Received from Alice: " + new String(packet.getData(), 0, packet.getLength())); socket.close(); } }
服务器端补充发送语句
在Host.java中添加发送回复的代码,确保回复能传递到客户端:
public class Host { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(1500); byte[] buf = new byte[65535]; System.out.println("Parameters successfully read. Listening on port 1500..."); while (true) { DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); if(new String(packet.getData(),0,packet.getLength()).equals("Bob")) { System.out.println("Bob has sent a connection request."); String test = "Hello Bob!"; packet.setData(test.getBytes()); // 新增发送语句,将回复发送给客户端 socket.send(packet); System.out.println("Text sent: " + new String(packet.getData(),0,packet.getLength())); } } } }
关键知识点
DatagramPacket.setData(byte[] buf)会替换数据包的内部缓冲区,并自动将length设置为该数组的长度。- UDP是无连接协议,每个数据包独立传输,接收时缓冲区的大小直接决定了能否容纳完整数据。
- 复用
DatagramPacket时,必须在接收前确保缓冲区足够大,否则会导致数据截断。
内容的提问来源于stack exchange,提问作者Zeffia
相关产品推荐
相关产品推荐

