我正在使用UDP套接字在Java中实现一个非常基本的服务器 - 客户端模型,我遇到了一个非常奇怪的问题。
我想做的就是让用户(客户端)向服务器发送消息,然后服务器将打印出来。
我有一个例子,但我遗漏了一些东西,因为我有以下问题:
如果客户端将消息“a”发送到服务器,则会正确接收该消息。 如果客户端将消息“bbb”发送到服务器,则会正确接收该消息。 如果客户端将消息“c”发送到服务器,则服务器将打印“cbb”作为收到的消息。
似乎服务器在收到新消息时会清理某种缓冲区。
这是我正在使用的代码:
服务器
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPServer {
public static void main(String args[]) throws Exception {
byte[] receive_data = new byte[256];
int recv_port;
DatagramSocket server_socket = new DatagramSocket(5000);
System.out.println("Server - Initialized server. Waiting for client on port 5000");
while (true) {
// System.out.println("Server - Listening for connections...");
DatagramPacket receive_packet = new DatagramPacket(receive_data, receive_data.length);
server_socket.receive(receive_packet);
String data = new String(receive_packet.getData());
InetAddress IPAddress = receive_packet.getAddress();
recv_port = receive_packet.getPort();
if (data.equals("q") || data.equals("Q")) {
System.out.println("Server - Exiting !");
break;
} else {
System.out.println("Server - Client from IP " + IPAddress + " @ port " + recv_port + " said : " + data + " (length: " + receive_packet.getLength() + ")");
}
}
}
}
客户端
public class UDPClient {
public static void main(String args[]) throws Exception {
byte[] send_data = new byte[256];
BufferedReader infromuser = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket client_socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
System.out.println("Client - Initialized the client...");
while (true) {
System.out.print("Client - Type Something (q or Q to quit): ");
String data = infromuser.readLine();
if (data.equals("q") || data.equals("Q")) {
System.out.println("Client - Exited !");
DatagramPacket send_packet = new DatagramPacket(send_data, send_data.length, IPAddress, 5000);
System.out.println("Client - Sending data : <" + data + ">");
client_socket.send(send_packet);
break;
} else {
send_data = data.getBytes();
DatagramPacket send_packet = new DatagramPacket(send_data, send_data.length, IPAddress, 5000);
System.out.println("Client - Sending data : <" + data + ">");
client_socket.send(send_packet);
}
}
client_socket.close();
}
}
我认为错误是微不足道的,但我在网络编程方面的技能有限,因此我不知道究竟是什么。
为了说清楚,我在不同终端上的同一台机器(mac)上运行服务器和客户端,以防万一它会影响到这种情况。
非常感谢任何帮助。
修改
......我回来回答我自己的问题。 问题是我没有定义服务器套接字应该读取的数据量。 因此,当我改变
String data = new String(receive_packet.getData());
带
String data = new String(receive_packet.getData(), 0, receive_packet.getLength());
一切顺利。
仅供将来参考,以及可能遇到同样问题的人:)
答案 0 :(得分:4)
根据结果构建String
时,您当前忽略了收到的数据包的长度。
使用DataSocket.receive(DatagramPacket)
后,DatagramPacket
的长度应设置为实际收到的长度:
数据报包对象的长度字段包含长度 收到的消息。如果消息比数据包长 长度,消息被截断。
这应解决接收方的问题:
String data = new String(receive_packet.getData(), 0, receive_packet.getLength());
为此,您还需要确保发送的数据大小合适。特别是,请勿使用send_data.length
构建传出的DatagramPacket
。这将始终使用缓冲区的全长)。 length参数并不总是send_data.length
(否则构造函数会从数组中获取它),它意味着该数组中消息的实际有用长度。
答案 1 :(得分:3)
在第一次通话时,这就是receive_data的样子:
--------------
|"a"| | |
--------------
第二次电话:
--------------
|"b"|"b"| "b" | notice that the "a" in data_receive was overwritten
--------------
在第三次通话中,您只发一封信, 所以被覆盖的数组的唯一部分是第一个元素:
--------------
|"c"|"b"| "b" |
--------------
这种情况正在发生,因为在发送到服务器的消息之间仍然存在receive_data
数组中的数据,一个简单的方法就是初始化接收循环内部的新数组。这样,每次收到消息时,您都会有一个新阵列等着你。
while (true)
{
byte[] receive_data = new byte[256];
......
}
答案 2 :(得分:0)
要解决此问题,您应使用 receive_packet 的长度来创建字符串或数组。
为了在服务器端获得更高的性能,最好在部分之前初始化 receive_packet ,并在while部分结束时重置其长度,以便在循环中重用它:String endDateValue = "07/01/2013";
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
Date endDate = sdf.parse(endDateValue);
Calendar cal = Calendar.getInstance();
cal.setTime(endDate);
cal.add(Calendar.MONTH, -6);
Date startDate = cal.getTime();
String startDateVaue = sdf.format(startDate);