有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

这是在回答BufferedWriter only works the first time时出现的

据我所知,Java文档(网上的许多帖子都证实了这一点)DatagramPacket不应该接受超过当前大小的数据。DatagramSocket的文档。接受说

This method blocks until a datagram is received. The length field of the datagram packet object contains the length of the received message. If the message is longer than the packet's length, the message is truncated.

因此,我制作了一个程序,它可以重用接收数据包并发送越来越长的消息

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);
        }
    }
}

输出是

Length 1 data 1
Length 2 data 12
Length 3 data 123
Length 4 data 1234
Length 5 data 12345
Length 6 data 123456
...

因此,即使长度为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的发行说明或特定于网络的发行说明中都没有提到这一点


共 (1) 个答案

  1. # 1 楼答案

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

    DatagramPacket recievedPacket = new DatagramPacket(buffer, buffer.length);
    

    根据文档,length()方法会告诉您当前存储在数据包中的消息的长度,它确实会这样做。改变

    byte[] buffer = new byte[100];
    

    byte[] buffer = new byte[10];
    

    yeilds的输出如下:

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