【问题标题】:UDP server can't send response to the client in efficient way [duplicate]UDP服务器无法以有效的方式向客户端发送响应[重复]
【发布时间】:2015-10-09 16:54:56
【问题描述】:

目前,我的 UDP 客户端仅向服务器发送两个命令 (td & TEMP)。 td 返回当前时间和日期。 TEMP 10.30 会将温度 10.30 转换为华氏温度并将结果返回给客户端。

问题:

当我输入td 命令首先它工作正常。之后,如果我输入TEMP 命令,它不会转换为华氏温度,而是转换为当前日期和时间(像这样的一些奇怪回复:Message Returned from Server : 50.5480-09 18:45:53)。那不是我想要的。另一方面,输入tdTEMP 反之亦然似乎工作正常。我不知道while循环中我的逻辑问题出在哪里。

UDP服务器:

    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;

}

UDP客户端:

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();
    }
}

【问题讨论】:

  • String fromServer = new String(receivePacket.getData(), 0, receivePacket.getLength()); ???

标签: java sockets udp client-server bufferedreader


【解决方案1】:

问题是客户端用于接收数据的字节数组中也包含了之前接收到的内容。当它收到来自服务器的响应时,只有一部分会被覆盖,因此其余部分也会与实际响应一起打印。

有很多方法可以解决这个问题。 您可以在 UDP 数据包中包含字符串的长度,也可以在每次从服务器获得响应后刷新缓冲区,以便下次响应时为空。你可以通过不同的方式来做到这一点。一种是将缓冲区的所有内容归零,或者每次都创建一个新缓冲区(您已经在服务器类中这样做了)。

查看客户端代码中的更改。只有 while 循环的开始需要一些改动。

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();
    }
}

如果您不想每次都创建缓冲区,也可以用全零重新初始化缓冲区。您需要在每次迭代中执行此操作。为此,您需要导入 Arrays 类。

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

【讨论】:

    【解决方案2】:

    您总是发送和接收原始数据,但您将其视为字符串。 getData() 返回 1024 字节的缓冲区,其中您只用50.5480 填充了前 7 个字节。其余的都是上次通话的垃圾。

    当您在时间之前获得温度时,它似乎对您有用(它并没有真正起作用,但问题并没有表现出来),因为时间字符串比温度字符串长并且它完全覆盖它。您将看到与您在收到时间后再次尝试测温时相同的不愉快效果。

    解决此问题的一种方法是在您的 UDP 消息中包含字符串的长度作为第一个条目,并在您从响应构造字符串时使用这是字符串长度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-19
      • 2014-06-20
      • 2017-07-30
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多