java - EOFExceptionon 读取 UDP

标签 java udp multicast eofexception

当 UDP 数据包的接收方尝试读取它时,我收到 EOFException。负责读取和解码 UDP 数据包的实例称为 Engager 对象。它们包含一个在 Engager 的构造函数中创建的套接字,以及一个名为 getEngagementPacketSize 的方法,该方法是接收和读取数据包的地方。这两种方法在这里一起引用:

public Engager(){
    MulticastSocket s=null;
    try{
        s=new MulticastSocket(6789);
        s.joinGroup(InetAddress.getByName("224.0.0.1"));
    }catch(IOException ex){
        ex.printStackTrace(System.out);
    }
    this.socket=s;
}

private int getEngagementPacketSize()throws Exception{
    byte[]bytes=new byte[Integer.BYTES]; 
    DatagramPacket dp=new DatagramPacket(bytes,Integer.BYTES);
    this.socket.receive(dp);

    ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
    ObjectInputStream ois=new ObjectInputStream(bais);
    int eps=ois.readInt();
    ois.close();

    return eps;
}

调用ois.readInt()时发生异常。

在发送方,数据包被创建并发送:

    InetAddress ia=null;
    try{
        ia=InetAddress.getByName("224.0.0.1");
    }catch(UnknownHostException ex){
        NewInstance_CannotConstructMulticastDestination x=new NewInstance_CannotConstructMulticastDestination(ac);
        x.initCause(ex);
        throw x;
    }

    MulticastSocket ms=null;
    try{
        ms=new MulticastSocket(6789);
        ms.joinGroup(ia);
    }catch(IOException ex){
        NewInstance_CannotConstructMulticastSocket x=new NewInstance_CannotConstructMulticastSocket(ac);
        x.initCause(ex);
        throw x;
    }

    NamedSovereignAlias nsa=new NamedSovereignAlias("Self");
    Engagement engagement=new Engagement(nsa,nsa,ac.getName(),ac.getPresynapticDelegate());

    byte[]engagementBytes=null;
    ByteArrayOutputStream baosEngagement=new ByteArrayOutputStream();
    try(ObjectOutputStream oos=new ObjectOutputStream(baosEngagement)){
        oos.writeObject(engagement);
        oos.close();
    }catch(Exception ex){
        NewInstance_CannotCreateBodyContent x=new NewInstance_CannotCreateBodyContent(ac);
        x.initCause(ex);
        throw x;
    }
    engagementBytes=baosEngagement.toByteArray();

    byte[]epsBytes=null;
    ByteArrayOutputStream baosEps=new ByteArrayOutputStream();
    try(ObjectOutputStream oos=new ObjectOutputStream(baosEps)){
        oos.writeInt(engagementBytes.length);
        oos.close();
    }catch(Exception ex){
        NewInstance_CannotCreateHeadContent x=new NewInstance_CannotCreateHeadContent(ac);
        x.initCause(ex);
        throw x;
    }
    epsBytes=baosEps.toByteArray();

    System.out.println("Length of header ["+epsBytes.length+"].");

    try{
        DatagramPacket dp=new DatagramPacket(epsBytes,epsBytes.length,ia,6789);
        ms.send(dp);
    }catch(Exception ex){
        NewInstance_CannotSendHeadPacket x=new NewInstance_CannotSendHeadPacket(ac);
        x.initCause(ex);
        throw x;
    }

我问这个问题是因为当我尝试读取两个 UDP 数据包中的第一个数据包时,我在接收器上收到 EOFException。因此,我的显示第二个数据包如何打包和发送的代码没有公开(它实际上被注释掉了,所以没有理由怀疑第二个数据包首先被接收)。第一个数据包仅包含一个整数,表示第二个数据包中的字节数。第二个数据包(如果已发送)包含一个参与实例。我没有在这里引用 Engagement 类,因为它的长度(而不是它的形式)很重要。发送方通知我第一个数据包的长度应为 10 个字节;这就是在发送数据包之前执行上面列表中的 System.println 语句时在系统输出窗口中观察到的内容。

为什么接收方无法从数据包中读取整数?问题出在发送方还是接收方?两者皆可吗?

收到的帮助很大。谢谢,

欧文。

最佳答案

Is the problem in the sender or the receiver? Could it be both?

问题出在接收端。您正在像这样分配数据包缓冲区:

byte[] bytes = new byte[Integer.BYTES]; 

这太小了。如果你看Object Serialization Specification ,您将看到序列化流以 2 字节“魔数(Magic Number)”和 2 字节协议(protocol)版本号开头。因此根据我的计算,缓冲区至少需要 8 个字节……甚至可能更多。

关于java - EOFExceptionon 读取 UDP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36806724/

相关文章:

java - 如何计算字符串中每个字母出现的次数?

java - Java中的代码结构是什么?

php - PHP socket_recv来自免费资源

c# - 如何在 C++ 中将整数转换为字节,以便 Unity 在通过 UDP 传输后可以理解它们

C# tcp 流 - 是否可以在没有监听器的情况下运行流?

c++ - 是否可以在 IIS 托管的 C++ 应用程序中启动自定义线程?

java - 用 Java 下载多个文件

Java:对象指针处理

mongodb - Spring XD - 作业中的 UDP

c++ - 丢包只发生在第一次运行