繁体   English   中英

最大限度地减少丢失的数据包对通过TCP发送的实时媒体流的影响的最佳方法是什么?

[英]What is the best way to minimize the impact of lost packets on a realtime media stream sent over TCP?

我们已经在Silverlight之上实现了一个音视频协作应用程序,并且正在尝试对其进行调整。 我们遇到的问题之一是每当数据包丢失时流等待时间就会增加:我们必须等待检测到数据包丢失,进行请求,然后等待重新发送丢失的数据包。 当然,这会影响我们音频流的一致性。 (如果可以的话,我们会切换到UDP,但Silverlight不支持该浏览器。我们还禁用了Nagle算法,因此通常,一旦提交byte []数组进行传输,我知道TCP数据包大小!=提交的数据量,但是在禁用Nagle算法的情况下,它很接近。而且我们有一个自适应抖动缓冲区,因此我们可以处理丢失的数据包,但是TCP / IP上丢失的数据包会大大增加我们需要缓冲的音频量,从而增加延迟。)

因此,我们正在尝试优化发送数据包的方式,以查看是否有任何方法可以减少丢失数据包的影响。 目前,我们正在考虑实施几种竞争解决方案:

(1)我们可以尝试使数据包更大。 当前,我们在同一TCP流上混合发送大(〜1024字节视频)数据包和小(〜70字节音频)数据包。 但是我们可以将音频和视频数据多路复用在一起,即,只要有房间,就可以将一些视频数据附加到音频数据包中。 这会使单个数据包更大一些,但会减少数据包的总数。

(2)我们可以将音频和视频分成两个单独的TCP流。 这意味着,如果视频流因丢失数据包而停顿,则音频流将不会停顿,反之亦然。 当然,这会稍微增加开销,并且不会减少发送的数据包的总数。

(3)我们可以将音频反向复用为多个单独的TCP流,然后在远端将它们重新组合。 这将有效地使我们“伪造”单个UDP样式的数据包传递。 如果我们有8个音频流,其中一个由于丢失数据包而停顿,其他流仍将能够按时传递其数据,而我们要做的就是处理1/8个音频数据包在停滞的流恢复之前不可用。 当然,这不是理想的选择,但是与使整个流停滞不前,以及重新传输丢失的数据包之前,无法播放任何数据包相比,这可能会带来更好的体验。

对这些可能性有何想法​​? 还有其他建议吗? 还是我们只需要对这三个代码进行编码,然后对其进行测试?

如果重新启用Nagle算法,您将(i)让TCP根据路径MTU而不是您自己的确定发送最大大小的缓冲区; (ii)完成您的建议(1)piggy带音频和视频数据包; (iii)减少包的总数。 带有和不带有Nagle算法的饱和TCP连接的稳态性能是相同的,因此,除了在初始窗口填充期间,您不会丢失任何东西。

您还应该运行可能提供的最大套接字发送缓冲区:至少128k,或者如果可能的话,增加两倍或四倍; 并且您还应该使用尽可能大的套接字接收缓冲区,尽管在连接套接字之前必须设置大于64k的套接字接收缓冲区,以便可以在TCP握手期间告知另一端窗口缩放。

该应用程序可以通过Internet使用吗? 是互联网质量造成丢包的原因吗? 如果是这样,除了将应用程序开发为尽可能地容错之外,您可能还需要确保Internet电路的质量是可接受的。 如今,良好的Internet电路的丢包率不应超过0.1%。 您可以使用我们的数据包丢失工具测试Internet电路和ISP。 它是免费使用的,所以请自助。

您如何确定造成丢包的原因是丢包?

我认为分离流不会有多大帮助,尝试保持音频/视频同步只会遇到更多问题。

无论哪种方式,无论您使用什么调整,都将受到TCP / IP的限制,要求重新传输数据包。 我想我要研究的最大问题是服务器和客户端上的TCP堆栈是否启用了一些更高级的选项。 我专门指的是选择性确认和快速重传(默认情况下,任何现代OS都应具有这些功能)。 快速重传将使客户端在检测到丢失的数据包时非常快地请求丢失的数据包,并且选择性确认将使服务器仅重新传输流的丢失部分。

最终,如果您不能容忍丢失单个数据包,听起来好像您没有使用足够大的抖动缓冲区。 也有可能您的应用程序在将数据发送到tcp堆栈的时间上不一致。 我会捕获一些数据包,并尝试很好地了解网络中正在发生的事情,然后看看您可以从那里做什么。

我不幸将第二个@Kevin Nisbet放在缓冲区上。 如果您使用的是TCP而不是UDP,则缓冲区的大小应与接收服务器有关丢失字节的通知以及到达客户端的缓冲区一样大。

由于TCP将数据作为有序流传递给应用程序,因此,当数据包丢失时,堆栈无法将任何其他字节传递给应用程序,直到将报告丢失字节的ack发送到服务器,进行处理并且字节到达客户端为止。 同时,保持应用程序运行的唯一方法是缓冲区。 您知道往返行程(包括处理)需要多长时间吗?

如果没有选择确认,丢失的字节之后收到的任何内容都是无用的,需要重新发送。 客户端将确认收到的最后一个字节,并且服务器需要从该点开始重新传输所有内容。

至少使用Selective Ack,服务器仅需要发送丢失的块,但是堆栈仍需要等待块到达。 它无法将到目前为止已收到的数据提供给应用程序,然后填写缺少的部分。 这就是UDP的作用:)也许您应该写MS ...

来自网络方面,我不愿(发送一点)发送相同内容的多个副本。 您的应用程序带宽充足吗? 也许某种冗余(FEC或类似的冗余)比复制您的内容更好。 此外,如果可能发生丢包,我认为将更多的流量推向网络并不明智。 您的计算机运行半双工吗? :-D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM