Java 为什么我可以在不重置长度的情况下重用DatagramPacket

Java 为什么我可以在不重置长度的情况下重用DatagramPacket,java,udp,Java,Udp,这是在回答问题时提出的 据我所知,Java文档(网络上的许多帖子都证实了这一点)DatagramPacket不应该接受超过其当前大小的数据。DatagramSocket.receive的文档说 此方法会一直阻塞,直到收到数据报为止。数据报数据包对象的长度字段包含所接收消息的长度。如果消息长于数据包的长度,则消息将被截断 因此,我制作了一个程序,它可以重用接收数据包并发送越来越长的消息 public class ReusePacket { private static class Sen

这是在回答问题时提出的

据我所知,Java文档(网络上的许多帖子都证实了这一点)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);
        }
    }
}
因此,即使长度为1,在下一次接收时,它也会收到一条长度为2的消息,并且不会截断它。但是,如果我手动设置包的长度,那么消息将被截断到此长度

我已经在OSX 10.7.2(Java 1.6.0_29)和Solaris 10(Java 1.6.0_21)上对此进行了测试。我的问题也是如此

为什么我的代码可以工作,并且可以在其他系统上工作

澄清一下,这种行为在过去的某个时候似乎已经改变了(至少对一些JVM来说),但我不知道以前的行为是否是一个bug。我很幸运它能以这种方式工作吗?我是否应该期望它在Oracle JVM、IBM JVM、JRockit、Android、AIX等上也能以同样的方式工作


在进一步调查和检查1.3.0、1.3.1和1.4.0的源代码后,Sun实现中引入了从1.4.0到1.4.0的更改,但是,JDK 1.4.0的发行说明或特定于网络的发行说明中都没有提到这一点。

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

DatagramPacket recievedPacket = new DatagramPacket(buffer, buffer.length);
根据文档,
length()
方法会告诉您当前存储在数据包中的消息的长度,它会这样做。改变

byte[] buffer = new byte[100];

“是”生成以下输出:

Length 1 data 1
Length 2 data 12
...
Length 9 data 123456789
Length 10 data 1234567890
Length 10 data 1234567890
Length 10 data 1234567890
...

我理解这一点,但考虑到如果您想自己将数据放入数据包,您不能使用setLength方法,而是要知道有一个数据包保护的bufLength不是您应该使用的documenter。此外,这意味着网络上几乎所有的例子,如和,都是错误的。当第二个包比第一个包大时,你的例子和我的例子都很容易显示为错误。第二篇文章是从2004年开始在jre 1.3.1上发表的,而我们的两个例子都是在1.6.*上发表的。这些示例中的问题很可能被认为是不受欢迎的,并在某个地方得到了修复。我同意旧的评论是错误的,但我仍然好奇我应该为以前的JVM编写什么样的正确方法,对于其他平台,如Adroid,AIX等。行为似乎已经改变,但我没有找到错误报告,也没有找到关于它的报告。将更新问题。在进一步调查和检查1.3.0、1.3.1和1.4.0的源代码后,Sun实现中引入了从1.4.0到1.4.0的更改,但是,JDK 1.4.0的发行说明或特定于网络的发行说明中都没有提到这一点。我想现在,最好的答案是,至少在Sun JDK 1.4.0中,它确实发生了变化,这可能在其他实现上也可能不起作用,YMMV;-)
byte[] buffer = new byte[10];
Length 1 data 1
Length 2 data 12
...
Length 9 data 123456789
Length 10 data 1234567890
Length 10 data 1234567890
Length 10 data 1234567890
...