Почему Java DatagramSocket не получает все пакеты udp, отправленные клиентами? - PullRequest
0 голосов
/ 27 августа 2018

мои клиенты отправляют пакеты udp с высокой скоростью.Я уверен, что мой уровень Java-приложения не принимает все пакеты udp, отправленные клиентами, потому что количество полученных пакетов в Wireshark и мое Java-приложение не совпадают.потому что wireshark получает больше пакетов udp, поэтому я уверен, что пакеты udp не потерялись в сети.

код здесь:

получает пакеты в потоке и предлагает LinkedBlockingQueue ив другом потоке принимают пакеты из LinkedBlockingQueue и затем вызывают onNext для субъекта rx-java.

socket = new DatagramSocket(this.port);
socket.setBroadcast(true);
socket.setReceiveBufferSize(2 * 1024 * 1024);

// thread-1
while (true) {
  byte[] bytes = new byte[532];
  DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
  try {
    this.socket.receive(packet);
    queue.offer(
        new UdpPacket(
            packet.getPort(), packet.getAddress().getHostAddress(), packet.getData()));
  } catch (IOException e) {
    e.printStackTrace();
  }
}


// thread-2
UdpPacket packet;
while ((packet = queue.take()) != null) {
     this.receiveMessageSubject.onNext(packet);
}

ОС хоста: Ubutnu 18.04

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

У меня недавно была похожая проблема на другом языке.Я не уверен, что он работает так же в Java, но это может быть полезно для вас.

Таким образом, когда пакеты данных попадают в сокет, они буферизируются, и вы устанавливаете размер буфера, но вы все равнотолько чтение одного пакета данных, хотя буфер может содержать больше.Поскольку вы обрабатываете по одной дейтаграмме за раз, ваш буфер заполняется еще больше, и в конечном итоге, когда он заполнится, данные могут быть потеряны, поскольку он не может хранить больше дейтаграмм.

Я проверил документация для DatagramSocket

Receives a datagram packet from this socket

Я не уверен в функциях, которые необходимо вызывать в Java, но вот небольшой фрагмент, который я использую.

while (!m_server->BufferEmpty()) {
        std::shared_ptr<Stream> inStream = std::make_shared<Stream>();
        std::vector<unsigned char>& buffer = inStream->GetBuffer();

        boost::asio::ip::udp::endpoint senderEndpoint = m_server->receive(boost::asio::buffer(buffer),
            boost::posix_time::milliseconds(-1), ec);

        if (ec)
        {
            std::cout << "Receive error: " << ec.message() << "\n";
        }
        else
        {
            std::unique_ptr<IPacketIn> incomingPacket = std::make_unique<IPacketIn>();
            incomingPacket->ReadHeader(inStream);

            m_packetProcessor->ProcessPacket(incomingPacket, senderEndpoint);

            incomingPacket.reset();
        }

        ++packetsRead;

        inStream.reset();

}

Это в основном говорит о том, что если сокет имеет какие-либо данные для текущего кадра в своем буфере, продолжайте читать дейтаграммы, пока буфер не станет пустым.

Не уверен в том, как работает LinkedBlockingQueue, ноэто также может вызвать проблемы, если оба потока пытаются получить к нему доступ одновременно.В вашей ветке чтения UDP вы можете быть заблокированы на некоторое время, а затем пакеты могут быть получены в течение этого времени.

0 голосов
/ 27 августа 2018

Очень сложно дать прямой ответ, но из моего опыта работы с UDP-сообщениями в Java действительно важно повысить производительность обработки сообщений , особенно с большими объемами данных.

Итак, вот несколько вещей, которые я хотел бы рассмотреть:

1) Вы правильно обрабатываете UDP-сообщения в другой очереди.Но очередь имеет ограниченный размер.Вам удается быстро обрабатывать сообщения?В противном случае очередь заполняется, и вы блокируете цикл while.Простое ведение журнала может дать вам знать, если это так.Поместить их в очередь, где они могут быть выделены на другом шаге, - это здорово, но вам также нужно убедиться, что обработка выполняется как обычно и очередь не заполняется.

2) Всеваши данные-граммы меньше 532 байтов?Возможно, некоторые потери происходят из-за больших сообщений, которые не заполняют буфер.

Надеюсь, это поможет,

...