Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java UDP套接字-数据留在服务器端_Java_Sockets_Udp - Fatal编程技术网

Java UDP套接字-数据留在服务器端

Java UDP套接字-数据留在服务器端,java,sockets,udp,Java,Sockets,Udp,我正在用Java实现一个非常基本的服务器-客户机模型,通过使用UDP套接字,我遇到了一个非常奇怪的问题 我只想让用户(客户端)向服务器发送一条消息,然后服务器将打印它 我有一个例子,但我遗漏了一些东西,因为我有以下问题: 如果客户端向服务器发送消息“a”,则会正确接收该消息。 如果客户端将消息“bbb”发送到服务器,则会正确接收该消息。 如果客户端向服务器发送消息“c”,则服务器将打印“cbb”作为接收到的消息 似乎服务器在收到新消息时确实清理了某种缓冲区 这是我正在使用的代码: 服务器 imp

我正在用Java实现一个非常基本的服务器-客户机模型,通过使用UDP套接字,我遇到了一个非常奇怪的问题

我只想让用户(客户端)向服务器发送一条消息,然后服务器将打印它

我有一个例子,但我遗漏了一些东西,因为我有以下问题:

如果客户端向服务器发送消息“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();
}
}

一切顺利


仅供将来参考,也供可能遇到相同问题的人参考:)

在您第一次打电话时,这是接收数据的样子:

 --------------
|"a"|    |    |
 --------------
第二次通话时:

 --------------
|"b"|"b"| "b" |             notice that the "a" in data_receive was overwritten
 --------------
第三次打电话时,你只发了一封信, 因此,数组中唯一被覆盖的部分是第一个元素:

 --------------
|"c"|"b"| "b" | 
 --------------
之所以会发生这种情况,是因为在发送给服务器的消息之间,
receive\u data
数组中仍有数据,一种简单的解决方法是在接收循环中初始化一个新数组。这样,每次收到消息时,都会有一个新的数组等待着您

while (true) 
{
    byte[] receive_data = new byte[256];
    ......
}

根据结果构造
字符串时,当前忽略了接收数据包的长度

使用后,应将
数据包的长度设置为实际接收的长度:

数据报数据包对象的长度字段包含 接收到的消息。如果消息比数据包的长度长 长度,则消息被截断

这将解决接收端的问题:

String data = new String(receive_packet.getData(), 0, receive_packet.getLength());

要使其正常工作,您还需要确保发送的数据大小正确。特别是,不要使用
send\u data.length
来构造传出
DatagramPacket
。这将始终使用缓冲区的整个长度)。长度参数并不总是
send\u data.length
(否则构造函数将从数组中获取),而是用于该数组中消息的实际有效长度。

要解决此问题,应使用receive\u packet的长度来创建字符串或数组。

为了提高服务器端的性能,最好在while段之前初始化receive\u packet,并在while段末尾重置其长度,以便在循环中重用:
receive\u packet.setLength(buffer.length)

@Sotiris谢谢,不过我更喜欢你的解决方案。它干净多了。哦,看来你自己找到了解决办法。当我完成打字时,我还没有注意到编辑。。。您没有提到任何有关发送数据长度的内容(我想您也已经修复了它)。为了真正正确,您是否应该进行某种字节到字符的转换?
while (true) 
{
    byte[] receive_data = new byte[256];
    ......
}
String data = new String(receive_packet.getData(), 0, receive_packet.getLength());