为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ITMISS 2021-08-13 16:44:36
我的客户以高速率发送 udp 数据包。我确定我的 java 应用程序层没有收到客户端发送的所有 udp 数据包,因为wireshark 中收到的数据包数量与我的 java 应用程序不匹配。因为wireshark接收更多的udp数据包所以我确定udp数据包没有在网络中丢失。代码在这里:在一个线程中接收数据包并提供给一个LinkedBlockingQueue线程,在另一个线程上消费从一个 rx-java 主题中获取数据包LinkedBlockingQueue,然后调用onNext它。socket = new DatagramSocket(this.port);socket.setBroadcast(true);socket.setReceiveBufferSize(2 * 1024 * 1024);// thread-1while (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-2UdpPacket packet;while ((packet = queue.take()) != null) {     this.receiveMessageSubject.onNext(packet);}主机操作系统: Ubutnu 18.04
查看完整描述

2 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

我最近在另一种语言中遇到了类似的问题。我不确定它在 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 读取线程中,您可能会被阻塞一段时间,然后在此期间可能会收到数据包。


查看完整回答
反对 回复 2021-08-13
?
慕仙森

TA贡献1827条经验 获得超8个赞

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

所以这里有一些我会考虑的事情:

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

2) 你所有的数据报都小于 532 字节吗?可能由于未填充缓冲区的较大消息而发生一些损失。

希望这可以帮助,


查看完整回答
反对 回复 2021-08-13
  • 2 回答
  • 0 关注
  • 554 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信