0
votes

I am implementing a simple java udp socket program. Here are the details:

  • Server side: suppose I create 2500 packets in server side, then inform the client that i'm gonna send 2500 packets, and each packet is packetSize bytes. then in a loop, each packet is created and then sent.
  • Client side: after being informed of the number of packets, in a for (or while), I wait for 2500 packets to be received.

Here is the problem: The for loop in client side never ends! that means 2500 packets are never received! Although I checked server side and it has sent them all.

I tried setting the socket's receive buffer size to 10 * packetSize using this:

socket.setReceiveBufferSize(10 * packetSize)

but it does not work.

How do you think I could solve this problem? I know UDP is not reliable but both client and server are running on different ports of the same computer!

Here is the code for server side:

for (int i = 0; i < packets; i++) {
            byte[] currentPacket = new byte[size];
            byte[] seqnum = intToByteArray(i);
            currentPacket[0] = seqnum[0];
            currentPacket[1] = seqnum[1];
            currentPacket[2] = seqnum[2];
            currentPacket[3] = seqnum[3];

            for (int j = 0; j < size-4; j++) {
                currentPacket[j+4] = finFile[i][j];
            }

            sendPacket = new DatagramPacket(currentPacket, currentPacket.length, receiverIP, receiverPort);
            socket.send(sendPacket);
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

and the client side:

int k = 0;
    while (true) {
        receivedBytes = new byte[size];
        receivePacket = new DatagramPacket(receivedBytes, size);
        socket.receive(receivePacket);
        allBytes.add(receivePacket.getData());
        k++;
        if (k == packets)
            break;
    }

allBytes is just a linked list containing received bytes. i use it to reassemble the final file.

P.S. This code works perfect for under 100Mb files. Thanks

1
The documentation of DatagramChannel says something along the lines of: "Data that can not fit in the buffer is silently discarded." Try making sure your buffer size is greater than or equal to the data you're expecting to receive. - Jacob G.
@JacobG. thanks. what do you mean by buffer? the byte array given to DatagramPacket as constructor? - SOFUser

1 Answers

1
votes

Update: tl;dr summary: Either packets is not properly initialized or use TCP, or add a sequence number in your UDP packet so that your client knows if it drops a packet and you can write code to handle that (request for a rebroadcast). This essentially makes it a rudimentary TCP anyways.

I have a suspicion that you never initialized packets so you never hit your break. Rewriting your while into a for loop can easily check if this is true. Assuming the first packet you send contains how many packets it will be receiving, and you initialize packets correctly then if your packets are being lost then your client side program will not end since receive() is a blocking method.

If you strongly suspect that your packets are being lost, then debug your client side and see how many received packets are in your LinkedList and compare that against how many are sent on the server side.

for(int i = 0; i < packets; i++) {
    receivedBytes = new byte[size];
    receivePacket = new DatagramPacket(receivedBytes, size);
    socket.receive(receivePacket);
    allBytes.add(receivePacket.getData());
}
System.out.println("All " + packet + " received.");

Switching to code to the above will let you know that if you never get to the print statement, then you know that you're losing packets since receive() is a blocking method and it means that your client side is stuck in the for loop. This is because the for loop can't be satisfied since if the server sends 2500 packets but the client only receives 2300 packets, it'll still be in the for loop at the receive() line waiting for 2301, 2302, ... packets and so on.

Since you have a file with upwards of 100MB or more that needs to be assembled I assume you can't tolerate loss, so either use TCP that will fulfill that requirement or handle that possibility in your code by creating your own header with each packet. This header can be as simple as an incrementing sequence number that the client will receive and read, if it skips a number from the previous packet then it will know that a packet was lost. At this point, you can have your client request the server to rebroadcast that specific packet. But at this point you just implemented your own crude TCP.