简体   繁体   English

为什么Java DatagramSocket不接收客户端发送的所有udp数据包?

[英]Why Java DatagramSocket doesn't receive all udp packet that clients have sent?

my clients send udp packets with high rate. 我的客户以高速率发送udp数据包。 i'm sure that my java app layer doesn't receive all udp packets that clients sent becuase the number of recieved packets in wireshark and my java app doesn't match. 我确定我的Java应用程序层不会收到客户端发送的所有udp数据包,原因是Wireshark中接收到的数据包的数量与我的Java应用程序不匹配。 because wireshark receive more udp packets so i'm sure udp packets didn't lost in network. 因为wireshark接收更多的udp数据包,所以我确定udp数据包不会在网络中丢失。

the code is here: 代码在这里:

receive packets in a thread and offer to a LinkedBlockingQueue and on another thread consume take packets from LinkedBlockingQueue and then call onNext on a rx-java subject. 接收数据包中的一个线程,并提供到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);
}

Host OS: Ubutnu 18.04 主机操作系统: Ubutnu 18.04

Very difficult to give a straight answer but from my experience with UDP message processing in Java it really matters to improve performance of processing the messages , especially with large volumes of data. 很难给出一个直接的答案,但是根据我在Java中处理UDP消息的经验, 提高消息处理的性能(尤其是处理大量数据)的性能确实很重要。

So here are some things that I would consider: 所以这是我要考虑的一些事情:

1) You are correct to process UDP messages on a different queue. 1)您正确在其他队列上处理UDP消息。 But, the queue has a limited size. 但是,队列的大小有限。 Do you manage to process messages fast? 您是否能够快速处理消息? Otherwise, the queue fills up and you are blocking the while loop. 否则,队列将填满,您将阻塞while循环。 Some simple logging there could let you know if this is the case. 如果是这种情况,一些简单的日志记录可能会让您知道。 Putting them on a queue where they can be pooped out on a different step is awesome but you also need to make sure that the processing is fast as way and that the queue does not fill up. 将它们放在一个队列中,可以在不同的步骤中将它们弹出,这是很了不起的,但是您还需要确保处理过程是快速的,并且队列不会填满。

2) Are all your data-grams less than 532 bytes? 2)您所有的数据报都小于532字节吗? Maybe some loss occurs due to larger messages that don't fill the buffer. 可能由于较大的消息未填充缓冲区而导致某些损失。

Hope this helps, 希望这可以帮助,

I had a similar issue to this recently in a different language. 最近我用另一种语言遇到了类似的问题。 I'm unsure if it works the same in Java, but this may be helpful to you. 我不确定它在Java中是否可以正常工作,但这可能对您有所帮助。

So as data packets come into the socket, they are buffered and you have set your buffer size, but you are still only reading a single data packet, even though the buffer could be holding more. 因此,当数据包进入套接字时,它们会被缓冲,并且您已经设置了缓冲区的大小,但是即使缓冲区可能容纳更多的数据包,您仍然只读取单个数据包。 As you're processing one datagram at a time, your buffer is filling up even more and eventually when its full, data could be lost as it can't store any more datagrams. 当您一次处理一个数据报时,缓冲区将填满甚至更多,最终当缓冲区满时,由于无法存储更多数据报,数据可能会丢失。

I checked the documentation for DatagramSocket 我检查了DatagramSocket文档

Receives a datagram packet from this socket

I'm unsure on the functions you would need to call in Java, but here's a little snippet that I am using. 我不确定在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();

}

This basically says that if the socket has any data for the current frame in its buffer, keep reading datagrams until the buffer is empty. 这基本上表明,如果套接字在其缓冲区中有当前帧的任何数据,请继续读取数据报,直到缓冲区为空。

Unsure on how the LinkedBlockingQueue works, but this could also be causing a bit of a problem if both threads are trying to access it at the same time. 不确定LinkedBlockingQueue工作方式,但是如果两个线程都试图同时访问它,这也可能会引起一些问题。 In your UDP reading thread you could be blocked for some time, and then packets could be received during this time. 在您的UDP读取线程中,您可能会被阻塞一段时间,然后在此期间可能会收到数据包。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM