Home > Enterprise >  UDP response packet contents getting cut short
UDP response packet contents getting cut short

Time:02-03

I'm trying to create a simple Java UDP Client-Server program. The server/host waits for an appropriate request from the client before doing something. Everything seems to be working fine but the reply from the host to the client is always truncated for some reason.

I assume it has something to do with the the length of "Bob" as all responses from the host is shortened to 3. I tried messing around with setLength() and the buffer size but can't seem to figure it out...

Client.java:

public class Client {

    public static void main(String[] args) throws Exception {
        
        //Use Java's built-in DatagramSocket and DatagramPacket to implement UDP
        DatagramSocket socket = new DatagramSocket(); //Create socket object to send data
        socket.setSoTimeout(5000); //Throw an exception if no data received within 5000ms
        
        //Create scanner to grab user input
        Scanner input = new Scanner(System.in);
        System.out.print("Please enter a message to send to Alice: ");
        String bobInput = input.nextLine(); //Storing user input
        input.close(); //Close scanner to prevent memory leaks
        
        byte[] buffer = new byte[65535];
        
        //Create packet containing message
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 1500);
        packet.setData(bobInput.getBytes());
        socket.send(packet); //Send message to host
        
        socket.receive(packet);
        
        System.out.println("Received from Alice: "   new String(packet.getData(),0,packet.getLength()));
        
        socket.close();
    }
}

Host.java

public class Host {

    public static void main(String[] args) throws Exception {
        
        //Use Java's built-in DatagramSocket and DatagramPacket to implement UDP
        DatagramSocket socket = new DatagramSocket(1500); //Create a socket to listen at port 1500
        byte[] buf = new byte[65535]; //Byte array to wrap
        
        System.out.println("Parameters successfully read. Listening on port 1500...");

        //While-loop to keep host running until terminated
        while (true) {
          DatagramPacket packet = new DatagramPacket(buf, buf.length); //Create a packet to receive message
          socket.receive(packet); //Receive the packet
          
          //If Alice receives a packet with the message "Bob"
          if(new String(packet.getData(),0,packet.getLength()).equals("Bob")) {
              System.out.println("Bob has sent a connection request.");
              
              String test = "Hello Bob!";
              packet.setData(test.getBytes());
              
              System.out.println("Text sent: "   new String(packet.getData(),0,packet.getLength()));
              
          }
        }
    }
}

Console output for client:

Please enter a message to send to Alice: Bob

Received from Alice: Hel

Console output for host:

Parameters successfully read. Listening on port 1500...

Bob has sent a connection request.

Text sent: Hello Bob!

It's my first time working with UDP so I apologize if its some basic mistake that I made.

CodePudding user response:

In the client, you create a packet of length 3 (because the content is 'Bob'). You use the same packet for a receive, which per the doc will then truncate the received data to the packet length.

The DatagramPacket class does not appear to distinguish 'length of underlying buffer' from 'length of data in buffer'.

Best to use separate packet structures; the send packet just needs to contain 'Bob'; the receive packet needs to be large enough for the maximum expected response.

(Debugging hint: figuring this out starts with noticing that it's unlikely to be mere coincidence that the lengths of the transmitted message and of the truncated received message are identical).

CodePudding user response:

Typically, in cases like this, you should create a custom protocol, either textual or binary, in which you specifies the length of the message to be read; it is not a TCP, so you can only wait until the entire datagram has been sent or received and after that parse the contents and extract the message.

This requires defining your own protocol to be used on top of UDP; there are two macro types of protocols: text-type and binary-type.

In text-type protocols you often make use of integers to put as prefixes that indicate the actual length of the message to be read. In fact if you know that the length of your messages, for example, stands at 32bit you can read the first four bytes of the datagram and know how many more you will have to read to get your string. The more complex text protocols make use of delimiting characters to specify a format that defines options and data; of this family you will certainly be familiar with HTTP.

In binary-type protocols it is a little more complex, you can have flags, various lengths referring to different fields that may or may not be optional. In short in this case you have to define for yourself a frame type to use and interpret. If you have to deal with fragmentation, options and variable lengths, I would recommend that you take a look at this type of format.

Keep also in mind that with UDP you should in real projects also handle the retransmission of lost packets.

Anyway, it's probably a typo, but your code is definitely missing a send() that actually sends the response data. So from your code we can't see what you actually send.

In conclusion, to answer you, from what can be inferred from the part of the code given and the output provided, you make use of setData() to send "Bob." The documentation for that method is as follows:

Set the data buffer for this packet. With the offset of this DatagramPacket set to 0, and the length set to the length of buf.

So, no matter what buffer you initialized the datagram with it will now be reduced to a maximum length of three. In fact, when you receive the response you read the message with getLength() which will always return three.

  • Related