Silverlight 将丢失的数据包对通过TCP发送的实时媒体流的影响降至最低的最佳方法是什么?

Silverlight 将丢失的数据包对通过TCP发送的实时媒体流的影响降至最低的最佳方法是什么?,silverlight,networking,tcp,network-protocols,multimedia,Silverlight,Networking,Tcp,Network Protocols,Multimedia,我们已经在Silverlight上实现了一个音频视频协作应用程序,并正在尝试对其进行调优。我们遇到的问题之一是,每当数据包被丢弃时,流延迟就会增加:我们必须等待数据包丢失被检测、请求,然后等待丢失的数据包被重新发送。当然,这会影响我们音频流的一致性。(如果可能的话,我们会切换到UDP,但Silverlight在浏览器中不支持。我们还禁用了Nagle算法,所以一般来说,只要我们提交一个字节[]要传输的数组,它被传输,并且在单个数据包中。我知道TCP数据包大小!=提交的数据量,但禁用Nagle算法后

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

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

(1) 我们可以试着把我们的包变大。目前,我们在同一个TCP流上混合发送大(~1024字节视频)数据包和小(~70字节音频)数据包。但是我们可以将音频和视频数据复用在一起,也就是说,只要有空间,我们就可以将一些视频数据附加到音频数据包上。这将使单个数据包稍大一些,但会减少数据包的总数

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

(3) 我们可以将音频反向多路复用成多个独立的TCP流,然后在远端重新组装它们。这将有效地允许我们“伪造”单个UDP风格的数据包传递。如果我们有8个音频流,其中一个由于数据包丢失而暂停,那么其他的音频流仍然能够按时发送数据,我们所要做的就是处理1/8的音频数据包不可用,直到暂停的数据流恢复。当然,这并不理想,但它可能会带来比整个流暂停更好的体验,并且在丢失的数据包重新传输之前无法播放任何数据包


对这些可能性有什么想法吗?还有其他建议吗?或者我们只需要把这三个都编码好,然后测试它们吗?

这个应用程序是通过互联网使用的吗?丢失数据包的原因是由于互联网质量吗?如果是这样的话,除了开发尽可能容错的应用程序外,您还可能希望确保Internet电路具有可接受的质量。如今,良好的互联网电路的数据包丢失率不应超过0.1%。您可以使用我们的工具测试Internet电路和ISP。可以自由使用,请自便。

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


您还应该运行您可能负担得起的最大套接字发送缓冲区:至少128k,或者如果可能的话,是它的两倍或四倍;您还应该使用尽可能大的套接字接收缓冲区,尽管在连接套接字之前必须设置>64k的套接字接收缓冲区,以便在TCP握手过程中告知另一端有关窗口缩放的信息。

您如何确定是数据包丢失导致了暂停

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

无论采用哪种方式,无论使用何种调整,都会受到TCP/IP的限制,需要重新传输数据包。我想我要研究的最大问题是服务器和客户端上的TCP堆栈是否启用了一些更高级的选项。我特别指的是选择性确认和快速重传(任何现代操作系统默认都应该有这些)。快速重传将使客户端在检测到丢失数据包时快速请求丢失的数据包,而选择性确认将使服务器仅重传流中丢失的部分


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

I second@Kevin Nisbet(不幸的是)。如果使用TCP而不是UDP,则缓冲区需要尽可能大,以便服务器得到丢失字节的通知,并让它们到达客户端

由于TCP以有序流的形式向应用程序传递数据,因此当数据包丢失时,堆栈无法向应用程序传递任何额外的字节,直到报告丢失字节的ack发送到服务器,并进行处理,并且字节到达客户端。 同时,让你的应用程序运行的唯一东西是缓冲区。你知道往返需要多长时间吗,包括处理

如果没有选择性Ack,在丢失字节之后接收到的任何内容都是无用的,需要重新传输。T