Linux 是否限制了我的应用程序的 UDP 传输?我如何才能看到它?

Linux 是否限制了我的应用程序的 UDP 传输?我如何才能看到它?

我目前正在开发两个应用程序,以通过自定义视频流“协议”运行。基本上是:

  • 服务器从网络摄像头捕获视频帧,将其切成几部分,然后通过 UDP 将这些部分发送给客户端。
  • 客户端接收所有帧部分,并处理所有“重新排序”:按正确的顺序放置各部分,将新帧存储在旧帧“上方”等等......这是实现“协议”的地方:客户端需要理解他们收到的视频数据,以便他们可以正确地重新排序,并且显示正确的框架

该机制本身运行良好(我承认经过了一番努力)。但是,现在我的应用程序正在运行,我发现我的客户端很难接收一些框架部分。假设客户端将成功检索第一个部分n帧,然后...等等recvfrom。我不会打扰你所有的应用程序的细节,但这里有一些统计数据:

  • 服务器每 40,000 微秒(25fps)捕获一帧(38,016 字节)。
  • 每帧分为 24 个部分(每部分 38,016 / 24 = 1584 字节)。

假设我们只有 1 个客户端。在网络方面,这意味着:

  • 每 40,000 微秒,服务器向客户端发送 24 个缓冲区(sendto)。每个缓冲区长度为 1584 字节。另一方面,客户端调用recvfrom24 次。
  • 在一秒钟内,服务器可以捕获 25 帧。这意味着在 1 秒内,它将向客户端发送 25 * 24 个帧部分。这代表每秒 25 * 24 * 1584 = 950,400 字节)。

我们还假设客户端在服务器发送时始终处于监听状态。现在,有了这些速率,客户端将能够跟上 1 或 2 秒。而应用程序才不是冻结,客户端最终将开始挂起recvfrom,就像服务器已经停止广播一样。

我为服务器添加了一些详细功能,以确保它继续广播,结果确实如此。几秒钟后,似乎服务器的sendto调用不再到达客户端的recvfrom调用。我检查了所有与网络相关的代码,由于代码非常简单,所以没什么问题:服务器构建一个缓冲区,调用sendto,然后开始准备下一个缓冲区……客户端只需等待缓冲区即可。

由于我无法在编程中找到解释,我开始相信有些东西......卡在网络上。似乎某个地方的某些东西阻止了我的 UDP 数据包在一段时间后到达客户端。现在,由于 UDP 完全不受控制,我无法找到从我的程序中检查缓冲区传输的方法。

但是,有没有办法让我知道系统是否传输我的数据包,或者最终达到其限制之一并开始丢弃它们?如果是这样,这是什么?限制机制,是否有办法配置我的系统,以便我的应用程序能够按照我编程的速率工作?

由于我的应用程序通过环回接口(127.0.0.1:n 上的服务器)进行通信,因此我认为添加有关此接口的信息是个好主意。我正在运行 GNU/Linux(内核 3.13.0)系统。

$ ifconfig lo
lo    Link encap:Local Loopback  
      inet addr:127.0.0.1  Mask:255.0.0.0
      inet6 addr: ::1/128 Scope:Host
      UP LOOPBACK RUNNING  MTU:65536  Metric:1
      RX packets:98821 errors:0 dropped:0 overruns:0 frame:0
      TX packets:98821 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:202639359 (202.6 MB)  TX bytes:202639359 (202.6 MB)

答案1

您可以使用它tcpdump来监控任一端的数据包。该工具可用于捕获标头或完整数据包。手册页包含有关如何过滤数据包的示例,以便您仅捕获您感兴趣的流量。

您的数据包大小似乎有点奇怪。如果您没有使用巨型帧,您的数据包可能会在网络上被分割成碎片进行传输。这可能是导致您出现问题的原因。

对于以太网连接来说,将帧拆分成 1472 字节或更少的部分更为合适。互联网连接的 MTU 可能更小,拆分成 1464 字节或更少的部分可能更为合适。

您可能希望在连接上进行 MTU 发现以防止碎片化。这将允许您避免或限制数据包碎片化。

相关内容