UDP 服务器无法有效地向客户端发送响应
UDP server can't send response to the client in efficient way
目前我的 UDP 客户端只向服务器发送两个命令 (td & TEMP
)。 td
返回当前时间和日期。 TEMP 10.30
将温度 10.30
转换为华氏度并将结果返回给客户端。
问题:
当我首先输入 td
命令时,它工作正常。之后,如果我输入 TEMP
命令,它不会转换为华氏度,而是转换为当前日期和时间(有些奇怪的回复是这样的:Message Returned from Server : 50.5480-09 18:45:53
)。那不是我想要的。另一方面,输入 td
和 TEMP
反之亦然似乎工作正常。我不知道 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();
}
}
你一直在发送和接收原始数据,但你把它当作字符串。 getData() returns 你的 1024 字节缓冲区,你只用 50.5480
填充了前 7 个字节。其余的都是上次通话的垃圾。
当你在时间之前获得温度时,它似乎对你有用(它实际上没有用,但问题并没有表现出来),因为时间字符串比温度字符串长并且它完全覆盖它。您会看到与在接收到时间后再次尝试获取温度相同的不愉快效果。
解决此问题的一种方法是将字符串的长度作为第一个条目包含在 UDP 消息中,并在从响应构造字符串时使用此字符串长度。
问题是客户端用来接收数据的字节数组也包含了之前接收到的内容。当它从服务器收到响应时,只有一部分被覆盖,因此其余部分也会与实际响应一起打印。
解决这个问题的方法有很多种。
您可以在 UDP 数据包中包含字符串的长度,也可以在每次从服务器收到响应后简单地刷新缓冲区,以便下次响应时缓冲区为空。再次有不同的方法可以做到这一点。一种是将缓冲区的所有内容清零,或者只是每次都创建一个新缓冲区(您已经在服务器中这样做了 class).
查看客户端代码的变化。只有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();
}
}
如果您不想每次都创建缓冲区,也可以使用全零重新初始化缓冲区。您需要在每次迭代中执行此操作。为此,您需要导入数组 class.
Arrays.fill( receiveData, (byte) 0 );
Arrays.fill( sendData, (byte) 0 );
目前我的 UDP 客户端只向服务器发送两个命令 (td & TEMP
)。 td
返回当前时间和日期。 TEMP 10.30
将温度 10.30
转换为华氏度并将结果返回给客户端。
问题:
当我首先输入 td
命令时,它工作正常。之后,如果我输入 TEMP
命令,它不会转换为华氏度,而是转换为当前日期和时间(有些奇怪的回复是这样的:Message Returned from Server : 50.5480-09 18:45:53
)。那不是我想要的。另一方面,输入 td
和 TEMP
反之亦然似乎工作正常。我不知道 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();
}
}
你一直在发送和接收原始数据,但你把它当作字符串。 getData() returns 你的 1024 字节缓冲区,你只用 50.5480
填充了前 7 个字节。其余的都是上次通话的垃圾。
当你在时间之前获得温度时,它似乎对你有用(它实际上没有用,但问题并没有表现出来),因为时间字符串比温度字符串长并且它完全覆盖它。您会看到与在接收到时间后再次尝试获取温度相同的不愉快效果。
解决此问题的一种方法是将字符串的长度作为第一个条目包含在 UDP 消息中,并在从响应构造字符串时使用此字符串长度。
问题是客户端用来接收数据的字节数组也包含了之前接收到的内容。当它从服务器收到响应时,只有一部分被覆盖,因此其余部分也会与实际响应一起打印。
解决这个问题的方法有很多种。 您可以在 UDP 数据包中包含字符串的长度,也可以在每次从服务器收到响应后简单地刷新缓冲区,以便下次响应时缓冲区为空。再次有不同的方法可以做到这一点。一种是将缓冲区的所有内容清零,或者只是每次都创建一个新缓冲区(您已经在服务器中这样做了 class).
查看客户端代码的变化。只有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();
}
}
如果您不想每次都创建缓冲区,也可以使用全零重新初始化缓冲区。您需要在每次迭代中执行此操作。为此,您需要导入数组 class.
Arrays.fill( receiveData, (byte) 0 );
Arrays.fill( sendData, (byte) 0 );