You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:05:45