Search code examples
javasocketsudpclient-serverbufferedreader

UDP server can't send response to the client in efficient way


For the moment my UDP client sends only two commands (td & TEMP) to the server. td gives back current time and date. TEMP 10.30 will convert the temperature 10.30 into farenheit and give the result back to the client.

PROBLEM:

When I input td command fisrt it works fine. After that if I enter TEMP command it doesn't get converted farenheit but the current date and time (some strange reply like this: Message Returned from Server : 50.5480-09 18:45:53). That is not what I want. On the other hand entering td and TEMP vice versa seems working fine. I dont know where is the problem with my logic inside the while loop.

UDPServer:

    public static void main(String arg[]) throws Exception {
    DatagramSocket serversocket = new DatagramSocket(9999);
    UDPServer udpserver = new UDPServer();
    byte[] receivedBuffer; // = new byte[1024];
    byte[] sentBuffer; //= new byte[1024];
    while (true) {
        receivedBuffer = new byte[1024];
        sentBuffer = new byte[1024];
        DatagramPacket receivedpacket = new DatagramPacket(receivedBuffer, receivedBuffer.length);
        System.out.println("Server Waiting for a message from Client.....");

        serversocket.receive(receivedpacket);
        String fromClient = new String(receivedpacket.getData());
        // enter td command to display the curerct date and time
        if (fromClient != null && fromClient.startsWith("td")) {
            InetAddress clientIP = receivedpacket.getAddress();
            System.out.println("Message received from client : " + fromClient + " at IP Address = "
                    + clientIP.getHostAddress() + ", Host Name = " + clientIP.getHostName());

            String toClient = udpserver.dateAndTime();
            sentBuffer = toClient.getBytes();
            DatagramPacket sendpacket = new DatagramPacket(sentBuffer, sentBuffer.length, clientIP, 8888);
            serversocket.send(sendpacket);
            System.out.println(" Reply Message is sent to client " + clientIP.getHostAddress());
        }

        // converting the TEMPERATURE into Farenheit
        if (fromClient != null && fromClient.startsWith("TEMP") && !fromClient.startsWith("td")) {

            InetAddress clientIP = receivedpacket.getAddress();
            System.out.println("Message received from client : " + fromClient + " at IP Address = "
                    + clientIP.getHostAddress() + ", Host Name = " + clientIP.getHostName());
            float temp = Float.parseFloat(fromClient.substring(fromClient.indexOf(' ') + 1));
            float tempInFaren = (float) (temp * 1.8 + 32.0);
            //float toClient = tempInFaren ;
            String convertIntoFarenheit = String.valueOf(tempInFaren);

            sentBuffer = convertIntoFarenheit.getBytes();
            DatagramPacket sendpacket = new DatagramPacket(sentBuffer, sentBuffer.length, clientIP, 8888);
            serversocket.send(sendpacket);
            System.out.println(" Reply Message is sent to client " + clientIP.getHostAddress());

        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ie) {
        }
    }
}

//method for returning current date and time
public String dateAndTime() {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d = new Date();
    String s = sdf.format(d);

    return s;

}

UDPClient:

public static void main(String args[]) throws Exception {
    byte[] sendData = new byte[1024];
    byte[] receiveData = new byte[1024];
    BufferedReader inFromKeyboard = new BufferedReader(new InputStreamReader(System.in));
    try {
        DatagramSocket clientSocket = new DatagramSocket(8888);
        InetAddress IPAddress = InetAddress.getByName("localhost");
        while (true) {
            System.out.println("Please enter the message to send to server: ");
            String sentence = inFromKeyboard.readLine();
            //sending time and date command
            if (sentence.startsWith("td") && !sentence.startsWith("TEMP")) {
                sendData = sentence.getBytes();
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9999);
                clientSocket.send(sendPacket);

                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                System.out.println(
                        "Message Sent to Server : " + sentence + "\n Now waiting for reply from Server....");
                clientSocket.receive(receivePacket);
                String fromServer = new String(receivePacket.getData());
                System.out.println("Message Returned from Server : " + fromServer);

            }
            //sending TEMP command

            if (sentence.startsWith("TEMP") && !sentence.startsWith("td")) {
                sendData = sentence.getBytes();
                DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9999);
                clientSocket.send(sendPacket);

                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                System.out.println(
                        "Message Sent to Server : " + sentence + "\n Now waiting for reply from Server....");
                clientSocket.receive(receivePacket);
                String fromServer = new String(receivePacket.getData());
                System.out.println("Message Returned from Server : " + fromServer);

            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Solution

  • The problem is the byte array used for receiving the data at the client side contains the previously received contents as well. Only a part of it is overwritten when it receives a response from the server and so the remaining also gets printed along with the actual response.

    There can be quite a few possible ways to solve this problem. You can either include the length of the string in the UDP packet or simply refresh the buffer each time after you get a response from the server so that it is empty for next response. There are again different ways you can do that. One is to zero all the contents of the buffer or simply create a new buffer each time (you already did this in the server class).

    See the changes in the client code. Only the starting of while loop needs some alteration.

    UDPClient:

    public static void main(String args[]) throws Exception {
        byte[] sendData;  
        byte[] receiveData;
        BufferedReader inFromKeyboard = new BufferedReader(new InputStreamReader(System.in));
        try {
            DatagramSocket clientSocket = new DatagramSocket(8888);
            InetAddress IPAddress = InetAddress.getByName("127.0.0.1");
            while (true) {
    
                 /*********************************
                  create a new buffer each time */
                    sendData = new byte[1024];
                    receiveData = new byte[1024];
                 /*********************************/
    
                System.out.println("Please enter the message to send to server: ");
                String sentence = inFromKeyboard.readLine();
                //sending time and date command
                if (sentence.startsWith("td") && !sentence.startsWith("TEMP")) {
                    sendData = sentence.getBytes();
                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9999);
                    clientSocket.send(sendPacket);
    
                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    System.out.println(
                            "Message Sent to Server : " + sentence + "\n Now waiting for reply from Server....");
                    clientSocket.receive(receivePacket);
                    String fromServer = new String(receivePacket.getData());
                    System.out.println("Message Returned from Server : " + fromServer);
    
                }
                //sending TEMP command
    
                if (sentence.startsWith("TEMP") && !sentence.startsWith("td")) {
                    sendData = sentence.getBytes();
                    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9999);
                    clientSocket.send(sendPacket);
    
                    DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                    System.out.println(
                            "Message Sent to Server : " + sentence + "\n Now waiting for reply from Server....");
                    clientSocket.receive(receivePacket);
                    String fromServer = new String(receivePacket.getData());
                    System.out.println("Message Returned from Server : " + fromServer);
    
                }
    
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    You can also reinitialize the buffer with all zeros if you do not want to create a buffer each time. You need to do this in each iteration. For this you need to import the Arrays class.

    Arrays.fill( receiveData, (byte) 0 );
    Arrays.fill( sendData, (byte) 0 );