Search code examples
javaudpmulticasteofexception

EOFExcepton reading UDP


I am receiving an EOFException when the receiver of a UDP packet attempts to read it. Instances that are charged with reading and decoding UDP packets are called Engager objects. They contain a socket which is created in the Engager's constructor, and a method called getEngagementPacketSize is where the packet is received and read. Both methods are quoted together here:

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

The exception occurs on the call to ois.readInt().

On the sender, the packet is created and sent thus:

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

I am asking this question because I receive an EOFException on the receiver when I try to read the first of two UDP packets. Hence, my code showing how the second packet is packaged and sent is not disclosed (it is actually commented out, so there is no reason to suspect that the second packet is being received first). The first packet contains just an integer that represents the number of bytes in the second packet. The second packet (if it were sent) contains a single instance of an Engagement. I haven't quoted the Engagement class here because it's length (not its form) matters. The sender informs me that the first packet should be 10 bytes in length; that is what one observes in the system output window when the System.println statement is executed in the listing above just before the packet is sent.

Why isn't the receiver able to read the integer from the packet? Is the problem in the sender or the receiver? Could it be both?

Help greatly received. Thanks,

Owen.


Solution

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

    The problem is on the receiving end. You are allocating the packet buffer like this:

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

    That is too small. If you look at the Object Serialization Specification, you will see that an a serialization stream starts with a 2 byte "magic number" and a 2 byte protocol version number. So by my calculations, the buffer needs to be at least 8 bytes ... and possibly more.