java - 在Java中接收UDP而不丢包

标签 java sockets networking rtp datagram

我有一个需要改进的库,因为它丢失了许多数据包。我想要接收 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可以看到数据包,我 如果可能的话,也希望能够检索到它。
  • 我知道环形缓冲区在丢失数据包时永远不会满,所以 这也不会让我丢失数据包。我尝试使用 BUFFER_SIZES 100 甚至 1000,但我已经在之前丢失了第一个数据包 总共已发送 1000 个数据包。

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

最佳答案

尝试使用 rtpSock.setReceiveBufferSize(size) 设置数据报套接字上的 SO_RCVBUF 大小。这只是对操作系统的建议,操作系统可能不会遵守它,特别是当它太大时。但我会尝试将其设置为 (SIZE_OF_PACKET * 30 * 100),其中 30 是突发中的数据包数量,100 是您无法跟上到达速度的毫秒数的猜测.

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

关于java - 在Java中接收UDP而不丢包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20213953/

相关文章:

python - Python 中的 Raspberry PI 服务器/客户端套接字

c - 如何确保服务器在可能的情况下监听 IPv6 而在其他情况下监听 IPv4?

java - 如何使用Eclipse JDT统计JDK中所有方法调用

.net - Web 场服务器使用的 WCF。错误 : The socket connection was aborted

java - 框架中的标签(Eclipse)

sockets - Golang UDP 和 TCP 并排

android - 确定设备公网ip

linux - 如何在 Linux 中仅使用 fs 和 bash 从 IPv4 ip 地址获取接口(interface)名称?

java - EditText 将字符串保存为整数然后将其乘以 3 不起作用?

java - 为什么在 Java 8 中对方法参数进行未经检查的转换时,返回类型的泛型会被删除?