BufferUnderflowException? Here?

21.3k views Asked by At

I am writing a small UDP server in Java. When the server receives a command ('GET_VIDEO'), he reads a file ('video.raw') and then sends it to the client.

Here is my code :

public class ServeurBouchon {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {

        byte[] buff = new byte[64];
        int port = 8080;
        DatagramPacket packet = new DatagramPacket(buff, buff.length);
        DatagramSocket socket = new DatagramSocket(port);

        System.out.println("Server started at 8080 ...");

        while (true) {
            socket.receive(packet);
            new ThreadVideo(socket, packet).run();
        }

    }

    public static class ThreadVideo extends Thread {

        private DatagramSocket socket;
        private DatagramPacket packet;

        public ThreadVideo(DatagramSocket socket, DatagramPacket packet) {
            this.packet = packet;
            this.socket = socket;
        }

        public void run() {
            String cmd = new String(packet.getData(), 0, packet.getLength());
            System.out.println("S:CMD reçu :" + cmd);
            if ("GET_VIDEO".equals(cmd)) {
                read_and_send_video(this.packet.getAddress());
            } else if ("TIMEOUT_REQUEST".equals(cmd)) {
                return;
            } else {
                System.out.println(" Exiting ...");
                return;
            }
            System.out.println("Fin .....");
        }

        private void read_and_send_video(InetAddress address) {
            System.out.println(" reading and sending video ...");
            File file = new File("./video/video.raw");
            ByteBuffer ibb = ByteBuffer.allocate(4);
            ibb.order(ByteOrder.BIG_ENDIAN);

            FileInputStream fis = null;
            DatagramPacket pack;
            byte[] buff = new byte[4];
            System.out.println(" Sending ...");
            try {
                fis = new FileInputStream(file);
                int size = 0;
                while ( size != -1) {
                    size = fis.read(buff, 0, buff.length);
                    System.out.println(" size = " + size);
                    ibb.put(buff);                  
                    System.out.println("Size : " + ibb.getInt());
                    int length = ibb.getInt();
                    byte[] fbuff = new byte[length];                    
                    fis.read(fbuff, 0, length);

                    pack = new DatagramPacket(fbuff, fbuff.length, address,
                            packet.getPort());
                    socket.send(pack);
                }

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

The raw file format is a continuous of "size + frame". The "size" variable contains the size(an int) of the next frame to be read. My problem is when I am reading the file(in the line ibb.getInt()), I get this exception :

Exception in thread "main" java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Buffer.java:480)
at java.nio.HeapByteBuffer.getInt(HeapByteBuffer.java:336)
at fr.sar.dss.bouchon.ServeurBouchon$ThreadVideo.read_and_send_video(ServeurBouchon.java:75)
at fr.sar.dss.bouchon.ServeurBouchon$ThreadVideo.run(ServeurBouchon.java:48)
at fr.sar.dss.bouchon.ServeurBouchon.main(ServeurBouchon.java:29)

Maybe I am doing this wrong but can somebody tells me where is my mistake?

Thansk for your help ;)

2

There are 2 answers

0
Erik On BEST ANSWER

This reads two ints.

System.out.println("Size : " + ibb.getInt());
int length = ibb.getInt();

Use this:

int length = ibb.getInt();
System.out.println("Size : " + length);
3
Dimitri On

I finally find the answer to my problem. Everytime you use the class ByteBuffer and his access method (like getInt(), getShort(), getFloat(), array()), you should call the method rewind to set the current buffer position to zero. This code totally works :

    System.out.println("Size : " + ibb.getInt());
    ibb.rewind();
    int length = ibb.getInt();
    ibb.rewind();

Thx for your help