Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中接收UDP而不丢弃数据包_Java_Sockets_Networking_Rtp_Datagram - Fatal编程技术网

在Java中接收UDP而不丢弃数据包

在Java中接收UDP而不丢弃数据包,java,sockets,networking,rtp,datagram,Java,Sockets,Networking,Rtp,Datagram,我有一个库,我需要改进,因为它正在下降到许多数据包。我想接收RTP流,但拖缆在一毫秒内发送30-40个数据包(MJPEG流)。在Wireshark中监视流量时,我可以看到数据包已完成。但是当我试图用Java接收它们时,我丢失了很多数据包 我已经能够通过实现一个环形缓冲区来改进库的行为,该缓冲区将在数据包可用时不断被填充,并实现一个从该缓冲区读取数据的独立读线程。但我仍然无法从我的套接字中获取wireshark中可以看到的所有数据包。通过RTP序列号,我可以在读卡器线程中监视所处理的数据包是否是预

我有一个库,我需要改进,因为它正在下降到许多数据包。我想接收RTP流,但拖缆在一毫秒内发送30-40个数据包(MJPEG流)。在Wireshark中监视流量时,我可以看到数据包已完成。但是当我试图用Java接收它们时,我丢失了很多数据包

我已经能够通过实现一个环形缓冲区来改进库的行为,该缓冲区将在数据包可用时不断被填充,并实现一个从该缓冲区读取数据的独立读线程。但我仍然无法从我的套接字中获取wireshark中可以看到的所有数据包。通过RTP序列号,我可以在读卡器线程中监视所处理的数据包是否是预期的数据包

以下代码正在处理数据包接收:

private volatile byte[][] packetBuffer = new byte[1500][BUFFER_SIZE];
private volatile DatagramPacket[] packets = new DatagramPacket[BUFFER_SIZE];
private volatile int writePointer = 0;

public void run() {
    Thread reader = new RTPReaderThread();
    reader.start();

    while (!rtpSession.endSession) {

        // Prepare a packet
        packetBuffer[writePointer] = new byte[1500];
        DatagramPacket packet = new DatagramPacket(packetBuffer[writePointer], packetBuffer[writePointer].length);

        // Wait for it to arrive
        if (!rtpSession.mcSession) {
            // Unicast
            try {
                rtpSession.rtpSock.receive(packet);
            } catch (IOException e) {
                if (!rtpSession.endSession) {
                    e.printStackTrace();
                } else {
                    continue;
                }
            }
        } else {
            // Multicast
            try {
                rtpSession.rtpMCSock.receive(packet);
            } catch (IOException e) {
                if (!rtpSession.endSession) {
                    e.printStackTrace();
                } else {
                    continue;
                }
            }
        }
        packets[writePointer] = packet;

        this.incrementWritePointer();           
        synchronized (reader) {
            reader.notify();
        }
    }
}
我已经知道:

  • 我知道UDP允许丢失数据包,但我仍然想这样做 达到最好的结果。如果wireshark能看到这个包,我 如果可能的话,我们也希望能够检索到它
  • 我知道丢失数据包时,环形缓冲区永远不会满,所以 这也不会让我丢包。我试过使用缓冲区大小 100甚至1000,但我已经在 总共发送了1000个数据包

所以问题是:从DatagramSocket接收尽可能多的数据包的最佳实践是什么?我可以改进对数据包突发的处理吗?

尝试使用
rtpSock.setReceiveBufferSize(size)
在数据报套接字上设置SO\u RCVBUF大小。这只是对操作系统的一个建议,操作系统可能不会接受它,特别是如果它太大的话。但我会尝试将其设置为(SIZE_OF_PACKET*30*100),其中30表示突发中的数据包数,100表示无法跟上到达速度的毫秒数


请注意,如果您的代码通常无法跟上到达速度的处理速度,则操作系统别无选择,只能丢弃数据包。

非常感谢,我将尝试这样做。我很容易跟上检索速度,只是在循环尝试获取数据包时,某些数据包有时已经消失了。请进一步注意,不要使用
synchronize
notify()
,而是创建
java.util.concurrent.LinkedTransferQueue
,在接收线程中执行
transfer()
将数据包放入队列,而处理线程执行
take()
从同一队列中执行。这将比synchronize/notify性能更好。感谢您的提示:java.util.concurrent.LinkedTransferQueue不幸的是,必须使用Java6…然后使用
LinkedBlockingQueue
。在几乎所有情况下,它的性能仍然优于
同步/通知