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

标签 java udp

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

据我对 Java Doc 的理解(网上的许多帖子都证实了这一点)DatagramPacket 不应接受超过其当前大小的数据。 DatagramSocket.receive 的文档说

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 而言),但我不知道旧行为是否是一个错误。我很幸运它以这种方式工作吗?我是否应该期望它在 Oracle JVM、IBM JVM、JRockit、Android、AIX 等上以相同的方式工作?

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

最佳答案

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

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

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

byte[] buffer = new byte[100];

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
...

关于java - 为什么我可以在不重置长度的情况下重用 DatagramPacket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8333813/

相关文章:

java - Hibernate:@ManyToOne,@OneToMany 在结果中给出空值

java - 在这个多态性练习中,我如何计算由一系列节点表示的方程式?

java - 在 Kafka Streams 中反序列化 POJO

Python - 检测远程计算机是否开启

java - TOMCAT 状态 404 试了所有错误

java - android构建错误: can't find symbol class IntDef

c - 如何产生持续的UDP流量?

C++ boost : initializing endpoint after contructor

java - 同一服务器监听不同的套接字

C 从客户端向服务器提交命令