![](/img/trans.png)
[英]Java DatagramSocket(UDP Socket) only receives when previously have sent a packet
[英]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.