2

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

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

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

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

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

对这些可能性有什么想法吗?还有其他建议吗?还是我们只需要编写所有三个代码,然后测试它们?

4

4 回答 4

1

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

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

于 2010-11-21T03:15:15.240 回答
0

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

于 2010-11-20T22:24:47.163 回答
0

I second @Kevin Nisbet on the buffer (unfortunately). If you're using TCP instead of UDP, the buffer needs to be as large as it takes for the server get notified about the missing bytes and for them to reach the client.

Since TCP delivers data to the application as an ordered stream, when a packet gets lost, the stack cannot deliver any additional byte to the app until the ack reporting the missing bytes is sent to the server, processed and the bytes arrive on the client. Meanwhile, the only thing keeping your app running is the buffer. Do you know how long does it take for the round-trip, including processing?

Without Selective Ack, anything received after that lost byte is useless and needs to be retransmitted. The client will ack the last byte received and the server needs to re-retransmit everything from that point on.

With Selective Ack at least the server only needs to send the missing chunk, but the stack needs to wait for the chunk to arrive nonetheless. It can't give the data it has received so far to the app and then fill in the missing parts. That's what UDP does :) Maybe you should write to MS...

Coming from the network side, I cringe (a bit) about sending multiple copies of the same content. Is bandwidth plentiful in your application? Maybe some sort of redundancy (FEC or similar) is better than duplicating your content. Besides, if packet loss could be happening I don't think it would be wise to shove more traffic on the network. Is your computer running half-duplex? :-D

于 2010-12-30T21:14:05.757 回答
0

您如何确定是丢包导致了停顿?

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

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

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

于 2010-11-21T03:42:21.463 回答