Java Udp сокеты, пакеты потеряны в localhost - PullRequest
0 голосов
/ 27 декабря 2018

Я реализую простую программу сокета Java UDP.Вот подробности:

  • Сторона сервера: предположим, что я создаю 2500 пакетов на стороне сервера, затем сообщаю клиенту, что я собираюсь отправить 2500 пакетов, и каждый пакет представляет собой байты packetSize.затем в цикле каждый пакет создается и затем отправляется.
  • Клиентская сторона: после получения информации о количестве пакетов в течение (или времени) я жду получения 2500 пакетов.

Вот проблема:цикл for на стороне клиента никогда не заканчивается!это означает, что 2500 пакетов никогда не принимаются!Хотя я проверил серверную часть, и он отправил их все.

Я попытался установить размер буфера приема сокета равным 10 * packetSize, используя это:

socket.setReceiveBufferSize(10 * packetSize)

, но это не работает.

Как вы думаете, я мог решить эту проблему?Я знаю, что UDP не надежен, но и клиент, и сервер работают на разных портах одного и того же компьютера!

Вот код для серверной части:

for (int i = 0; i < packets; i++) {
            byte[] currentPacket = new byte[size];
            byte[] seqnum = intToByteArray(i);
            currentPacket[0] = seqnum[0];
            currentPacket[1] = seqnum[1];
            currentPacket[2] = seqnum[2];
            currentPacket[3] = seqnum[3];

            for (int j = 0; j < size-4; j++) {
                currentPacket[j+4] = finFile[i][j];
            }

            sendPacket = new DatagramPacket(currentPacket, currentPacket.length, receiverIP, receiverPort);
            socket.send(sendPacket);
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

и клиентской стороны:

int k = 0;
    while (true) {
        receivedBytes = new byte[size];
        receivePacket = new DatagramPacket(receivedBytes, size);
        socket.receive(receivePacket);
        allBytes.add(receivePacket.getData());
        k++;
        if (k == packets)
            break;
    }

allBytes - это просто связанный список, содержащий полученные байты.Я использую его для повторной сборки окончательного файла.

PS Этот код отлично подходит для файлов размером менее 100 МБ.Спасибо

1 Ответ

0 голосов
/ 27 декабря 2018

Обновление: tl; dr сводка: либо packets не инициализирован должным образом, либо используется TCP, либо добавьте порядковый номер в ваш пакет UDP, чтобы ваш клиент знал, отбрасывает ли он пакет, и вы можете написать код для его обработки (запрос на ретрансляцию).В любом случае это делает его рудиментарным TCP.

У меня есть подозрение, что вы никогда не инициализировали packets, поэтому вы никогда не нажали свой break.Переписав ваш while в цикл for, можно легко проверить, верно ли это.Предполагая, что первый отправленный вами пакет содержит сколько пакетов он будет получать, и вы правильно инициализируете packets, тогда, если ваши пакеты будут потеряны, ваша клиентская программа не завершится, так как receive () является методом блокировки.

Если вы сильно подозреваете, что ваши пакеты теряются, отладьте свою клиентскую сторону и посмотрите, сколько полученных пакетов есть в вашем LinkedList, и сравните это с количеством отправленных на стороне сервера.

for(int i = 0; i < packets; i++) {
    receivedBytes = new byte[size];
    receivePacket = new DatagramPacket(receivedBytes, size);
    socket.receive(receivePacket);
    allBytes.add(receivePacket.getData());
}
System.out.println("All " + packet + " received.");

Переключение на код, описанный выше, даст вам знать, что если вы никогда не доберетесь до оператора print, то вы будете знать, что теряете пакеты, поскольку receive () является методом блокировки и это означает, что ваша клиентская сторона застрялав цикле for.Это связано с тем, что цикл for не может быть выполнен, поскольку, если сервер отправляет 2500 пакетов, но клиент получает только 2300 пакетов, он все равно будет находиться в цикле for в строке receive (), ожидая 2301, 2302,... пакеты и т. д.

Поскольку у вас есть файл размером более 100 МБ и более, который необходимо собрать, я предполагаю, что вы не можете допустить потери, поэтому либо используйте TCP, который будет выполнять это требование, либо обрабатывать еговозможность в вашем коде, создавая свой собственный заголовок с каждым пакетом.Этот заголовок может быть таким же простым, как увеличивающийся порядковый номер, который клиент получит и прочитает, если он пропустит число из предыдущего пакета, то он будет знать, что пакет был потерян.В этот момент ваш клиент может запросить у сервера ретрансляцию этого конкретного пакета.Но на данный момент вы только что реализовали свой собственный сырой TCP.

...