При отправке пакетов дейтаграмм данные пакета дублируются. (Джава)

avatar
bean123456
8 апреля 2018 в 10:27
890
2
1

UDPclient:

public static void main(String[] args) {
    // TODO Auto-generated method stub
    DatagramSocket socket;
    DatagramPacket packet;
    String str = "";
    byte[] buffer;
    String serverIP = "192.168.0.16";
    int serverPORT = 10789;
    Scanner sc = new Scanner(System.in);

    try {
        socket = new DatagramSocket();
        while(true) {
            System.out.print("To server : ");
            str = sc.nextLine();
            if(str.equals("exit")) {
                System.out.println("exit");
                break;
            }
            buffer = str.getBytes();
            packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(serverIP), serverPORT);
            socket.send(packet);
            System.out.println("sent message : " + str);
        } 
        socket.close();
    } catch (skip)

UDP-сервер:

byte[] buffer = new byte[1024];

public static void main(String[] args){
    int port = 10789;
    DatagramSocket socket;
    DatagramPacket packet;
    byte[] buffer = new byte[1024];

    try {
        socket = new DatagramSocket(port);
        packet = new DatagramPacket(buffer, buffer.length);
        while(true){
            socket.receive(packet);
            String text = new String(packet.getData());
            if(text.equals("exit")){
                System.out.println("exit");
                break;
            }
            System.out.println("received : "+text);
        }
    }

Когда я ввожу ввод много раз, данные пакета дублируются.

Пример: Пока я печатал:

тип abcdeg

отображается abcdeg на сервере

тип qwe

отображается qwedeg на сервере

Что не так? Как очистить буфер?

Источник
Samuel Peter
8 апреля 2018 в 10:34
0

В клиенте buffer по-прежнему имеет значение null, когда вы вызываете buffer.length, что должно вызывать NPE. Я полагаю, что какой-то код отсутствует?

bean123456
8 апреля 2018 в 10:51
0

Я переместил packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(serverIP), serverPORT); в конец buffer = str.getBytes();

Ответы (2)

avatar
Samuel Peter
8 апреля 2018 в 11:00
1

В коде сервера один и тот же буфер повторно используется для всех полученных пакетов (что хорошо). Однако это означает, что данные из предыдущих пакетов присутствуют в буфере до тех пор, пока они не будут перезаписаны. Как вы видели, когда вы получаете пакет, который короче предыдущего, перезаписываются только первые байты в буфере, вплоть до длины полученного сообщения.

new String(packet.getData()) позволяет конструктору String определить длину данных, просматривая содержимое буфера. Вместо этого используйте другой конструктор, который позволяет указать длину данных: new String(packet.getData(), 0, packet.getLength()).

bean123456
8 апреля 2018 в 14:21
0

Я понял и у меня получилось. действительно ценю это. Кстати. когда на клиенте получена строка «выход», как определить строку «выход»? Я добавил if(text.equals("exit")){ System.out.println("exit") break; }, но ничего не произошло

bean123456
8 апреля 2018 в 14:27
0

в то время как оператор все еще зацикливается.

Samuel Peter
8 апреля 2018 в 18:28
1

@H.Bin Проблема в том, что когда пользователь вводит «выход» на клиенте, клиент немедленно завершает работу, не отправляя строку на сервер. Чтобы исправить это, вы можете поместить блок if(str.equals("exit")) { System.out.println("exit"); break; } в конец цикла клиента.

avatar
sayboras
8 апреля 2018 в 11:00
0

Вы не можете очистить буфер со стороны сервера, так как один и тот же буфер используется для всех подключений. Однако вы можете использовать packet.getLength() и packet.getOffset() для проверки длины и смещения полученных данных.

String received 
          = new String(packet.getData(), packet.getOffset(), packet.getLength());