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

时间:2018-08-27 05:59:15

标签: java linux sockets udp datagram

我的客户端以高速率发送udp数据包。 我确定我的Java应用程序层不会收到客户端发送的所有udp数据包,原因是Wireshark中接收到的数据包的数量与我的Java应用程序不匹配。 因为Wireshark接收到更多的udp数据包,所以我确定udp数据包不会在网络中丢失。

代码在这里:

在一个线程中接收数据包并提供给A(:,1) = x(:); A(:,2) = y(:); ,而在另一个线程中,消耗LinkedBlockingQueue的数据包,然后在一个线程上调用LinkedBlockingQueue  rx-java主题。

onNext

主机操作系统: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); }

2 个答案:

答案 0 :(得分:0)

很难给出一个直接的答案,但是根据我在Java中处理UDP消息的经验,提高处理消息的性能确实很重要,尤其是在处理大量数据时。

这是我要考虑的一些事情:

1)您正确地在其他队列上处理UDP消息。但是,队列的大小有限。您是否能够快速处理消息?否则,队列将填满,您将阻塞while循环。如果是这种情况,一些简单的日志记录可能会让您知道。将它们放在一个队列中,可以在不同的步骤中将它们弹出,这很了不起,但您还需要确保处理速度快并且队列不会填满。

2)您所有的数据报是否都小于532字节?也许是由于较大的邮件未填充缓冲区而造成一些损失。

希望这会有所帮助,

答案 1 :(得分:0)

最近我用另一种语言遇到了类似的问题。我不确定它是否在Java中也可以使用,但这可能对您有所帮助。

因此,当数据包进入套接字时,它们将被缓冲,并且您已经设置了缓冲区大小,但是即使缓冲区可能容纳更多数据包,您仍然仅读取单个数据包。当您一次处理一个数据报时,缓冲区将填满甚至更多,最终当缓冲区满时,由于无法存储更多数据报,数据可能会丢失。

我在documentation中检查了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读取线程中,您可能会被阻塞一段时间,然后在这段时间内可能会收到数据包。