2017-08-27 52 views
0

我有一个应用程序,其主要目的是将RTP流转换为HTTP流。一个线程正在接收RTP数据包并将它们写入循环缓冲区,另一个线程充当迷你网络服务器,并通过从该缓冲区读取来应答HTTP请求(一次只能发生一个GET请求)。在send()中很长的块,似乎与线程有关,而不是TCP

一旦接收到GET,这个HTTP线程就是一个简单的循环,只要循环缓冲区中有东西,就调用send()。但是有时候,send()会阻塞大量的时间(比如> 1s),从而产生音频丢失。

要清楚的是,RTP数据包能够实时到达,而不会在这里超过或下溢。 HTTP套接字是故意阻塞的,因为预期当接收器不需要音频(在其自己的缓冲器上足够多)时,接收器使用TCP来调节其流。但是HTTP客户端并没有被音频所淹没,因为RTP源再次只是在实时执行。

但是,很明显,发生了其他事情,我观察到在Linux,MacOS和Windows(代码适用于所有这些)以及两种不同的网络拓扑结构上。

我想知道如果在send()长的块不是起因于TCP流量控制别的东西,像什么我有什么情况发生时,在发送线程块()

回答

2

获取失踪一个wireshark踪迹,所以你可以看到TCP失速发生的地方。我怀疑发生了什么是以下任何一种情况:

  1. 您实际上发送的速度比客户端消耗的速度快。我认为你已经排除了...

  2. 更可能的情况是IP数据包正在丢失,并且TCP卡住等待ACK,超时,然后重新传输。与此同时,您的发送线程正试图将更多数据塞入套接字,并且它正在备份并最终被阻塞。

一个简单的事情,你所能做的就是尽量用你送的插座上增加了发送缓冲区(SO_SNDBUF)。该值指定在阻止之前应用程序可以写入套接字的未传输字节数。如果可能的话,增加客户端的接收缓冲区(SO_RCVBUF)。这样,如果网络打了几秒钟,你的套接字在阻塞之前需要更长的时间才能填满。

int size = 512*1024; 
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); 
+0

谢谢 - 我不介意线程被阻塞,因为在这一点上它的唯一目的是发送数据,但你指出可能真正的问题是数据包丢失和ACK超时。如果可以在每个套接字的基础上改变,我必须进行投资。我可能没有看到与其他音频应用程序的问题,因为他们有可能提前发送大量音频,所以网络连接是 –

+0

评论超时:-( 我必须调查是否以及如何TCP窗口和相关参数可以在每个插槽的基础上改变,我从来没有看到 我试过的两个网络肯定不是非常可靠,因为我可以看到,在RTP(UDP)端有很多丢失的paquet,我必须要求重新发送 –

+0

您需要增加SO_SNDBUF,因为这样可以减少一些此类问题,因为它可以为您提供一个更大的“泄漏桶”来处理。另一个需要研究的问题是如何降低每个套接字或系统上的TCP RTO值(这个**不是** SO_SNDTIMEO - 这是不同的)由于RTO是一个动态值,可以在连接保持打开状态时进行调节,所以您可能需要调整系统设置。尝试[man 7 tcp](https://linux.die。net/man/7/tcp),或者搜索“tcp socket change rto”。关于这个话题有很多需要阅读。 – selbie