2017-08-27 34 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