0
votes

I am trying to implement a udp image transfer program in java. The sender breaks the image up into 1024 byte packets where the first 2 bytes are a short carrying the sequence number and the 3rd byte is a flag indicating whether the packet is the last one or not.

When I execute the receiver and send the image using the sender the transferred image is incomplete and has strange colours on it. Other times when I execute the receiver, it will stick after sending several hundred packets.

Here is the code for the receiver which takes the received packets and writes it to a byte stream.

        double DATAGRAM_MAX_SIZE = 1024;
        byte[] recieveData = new byte[(int) DATAGRAM_MAX_SIZE];
        ByteArrayInputStream bais = new ByteArrayInputStream(recieveData);
        DataInputStream dis = new DataInputStream(bais);

        // Loop until all packets received
        byte isLast = 0;
        while(true) {
            receievePacket = new DatagramPacket(recieveData, recieveData.length);
            try {
                receieveSocket.receive(receievePacket);
            } catch (IOException e) {
                System.out.println("Error receieving packet");
                e.printStackTrace();
            }
            Short sequenceNum = dis.readShort();
            isLast = dis.readByte();
            System.out.println(recieveData[0] + " " + recieveData[1] +" " +  recieveData[2]);
            if (!seenSeq.contains(sequenceNum)) {
                seenSeq.add(sequenceNum);
                bos.write(recieveData, 3, (int) DATAGRAM_MAX_SIZE-3);
            }
            dis.reset();
            // Terminate loop if last packet received
            if (isLast == 1) {
                break;
            }
        }

        //  Byte array to hold image data from stream 
        byte[] imageData = bos.toByteArray();

Whenever the receiver does manage to receieve all packets here is the resulting image: enter image description here

2
I often suggest you implement a transfer/connection using TCP before attempting UDP as it is much more complex to use reliably.Peter Lawrey

2 Answers

6
votes
  1. If you are connecting to yourself make sure to make use of:

    Socket.setReceiveBufferSize
    

    The problem I encountered is that sending to yourself is so fast that at some point buffer overflows and some packets are simply discarded. (even assuming the ideal network conditions when connecting to yourself)

  2. Do testing. What packets you are actually sending. Try to create from the Datagram Packets on sender side itself your image, so you are sending what you actually expect. On receiver side check exactly which packets are lost and try to observe the pattern.

  3. As stated before UDP is unrealiable - packets may not arrive and may also arrive in wrong sequence. Check that you place packets out of order in a correct sequence.

  4. Also note that upon setting up the connection several packets can be lost if sender say started milliseconds before the receiver, so receiver should always be up and ready before sender starts doing anything. (this happens even on localhost if threads are not strictly synchronized)

Sending image over UDP is not really great idea. Image, text are type of data which should really be sent over TCP - partial loss here can have significant impact. VOIP is the one caring less for the packet loss especially with interleaving and compression.

2
votes

UDP is not a reliable transport protocol. If you want reliability, you need to implement it yourself or use TCP Read UDP here