簡體   English   中英

為什么Java DatagramSocket不接收客戶端發送的所有udp數據包?

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

我的客戶以高速率發送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

很難給出一個直接的答案,但是根據我在Java中處理UDP消息的經驗, 提高消息處理的性能(尤其是處理大量數據)的性能確實很重要。

所以這是我要考慮的一些事情:

1)您正確在其他隊列上處理UDP消息。 但是,隊列的大小有限。 您是否能夠快速處理消息? 否則,隊列將填滿,您將阻塞while循環。 如果是這種情況,一些簡單的日志記錄可能會讓您知道。 將它們放在一個隊列中,可以在不同的步驟中將它們彈出,這是很了不起的,但是您還需要確保處理過程是快速的,並且隊列不會填滿。

2)您所有的數據報都小於532字節嗎? 可能由於較大的消息未填充緩沖區而導致某些損失。

希望這可以幫助,

最近我用另一種語言遇到了類似的問題。 我不確定它在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讀取線程中,您可能會被阻塞一段時間,然后在此期間可能會收到數據包。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM