为什么我可以重用DatagramPacket而不重置长度

Rog*_*sjö 8 java udp

在回答BufferedWriter时,第一次只能使用它

据我所知,Java Doc(网上很多帖子证实了这一点),DatagramPacket不应该接受比当前大小更多的数据.DatagramSocket.receive的文档说

此方法将阻塞,直到收到数据报.数据报包对象的长度字段包含接收消息的长度.如果消息长于数据包的长度,则消息将被截断.

因此,我制作了一个程序,它重用接收数据包并发送更长和更长的消息.

public class ReusePacket {

    private static class Sender implements Runnable {

        public void run() {
            try {
                DatagramSocket clientSocket = new DatagramSocket();
                byte[] buffer = "1234567890abcdefghijklmnopqrstuvwxyz".getBytes("US-ASCII");
                InetAddress address = InetAddress.getByName("127.0.0.1");

                for (int i = 1; i < buffer.length; i++) {
                    DatagramPacket mypacket = new DatagramPacket(buffer, i, address, 40000);
                    clientSocket.send(mypacket);
                    Thread.sleep(200);
                }                  
                System.exit(0);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String args[]) throws Exception {
        DatagramSocket serverSock = new DatagramSocket(40000);
        byte[] buffer = new byte[100];
        DatagramPacket recievedPacket = new DatagramPacket(buffer, buffer.length);

        new Thread(new Sender()).start();

        while (true) {
            serverSock.receive(recievedPacket);
            String byteToString = new String(recievedPacket.getData(), 0, recievedPacket.getLength(), "US-ASCII");
            System.err.println("Length " + recievedPacket.getLength() + " data " + byteToString);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是

Length 1 data 1
Length 2 data 12
Length 3 data 123
Length 4 data 1234
Length 5 data 12345
Length 6 data 123456
...
Run Code Online (Sandbox Code Playgroud)

因此,即使长度为1,对于下一次接收,它将获得长度为2的消息,并且不会截断它.但是,如果我手动设置包的长度,则消息将被截断为此长度.

我在OSX 10.7.2(Java 1.6.0_29)和Solaris 10(Java 1.6.0_21)上测试了这个.所以对我的问题.

为什么我的代码可以运行并且可以期望它在其他系统上运行?

为了澄清,这种行为似乎在过去的某个时候发生过变化(至少对于某些JVM而言),但我不知道旧的行为是否是一个错误.我很幸运它以这种方式工作,我是否应该期望它在Oracle JVM,IBM JVM,JRockit,Android,AIX等上以相同的方式工作?

在进一步调查并检查1.3.0,1.3.1和1.4.0的源代码之后,从1.4.0开始在Sun实现中引入了更改,但是,在发行说明或网络特定发行说明中没有提及此更改. JDK 1.4.0.

小智 7

这里有两种不同的长度.在构造函数中数据包的长度设置为100:

DatagramPacket recievedPacket = new DatagramPacket(buffer, buffer.length);
Run Code Online (Sandbox Code Playgroud)

根据文档,该length()方法告诉您当前存储在数据包中的消息的长度.更改

byte[] buffer = new byte[100];
Run Code Online (Sandbox Code Playgroud)

byte[] buffer = new byte[10];
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

Length 1 data 1
Length 2 data 12
...
Length 9 data 123456789
Length 10 data 1234567890
Length 10 data 1234567890
Length 10 data 1234567890
...
Run Code Online (Sandbox Code Playgroud)