2017-08-27 10 views
0

RTPストリームをHTTPストリームに変換することを主な目的とするアプリケーションがあります。 1つのスレッドはRTPパケットを受信して​​循環バッファに書き込み、もう1つのスレッドはミニWebサーバとして動作し、そのバッファから読み取ることでHTTPリクエストに応答します(一度に1つのGET要求しか発生しません)。send()の非常に長いブロックは、TCPに関係なく、スレッドに関連しているようです。

このHTTPスレッドは、GETが受信されると循環バッファに何かがあるときにsend()を呼び出す単純なループです。しかし時には、send()ブロックが狂った時間(> 1秒)でブロックされ、オーディオドロップアウトが発生することがあります。

明確にするため、RTPパケットはリアルタイムで到着します。ここではオーバーフローまたはアンダーフローは発生しません。 HTTPソケットは、受信者がオーディオを必要としないときにTCPを使用してフローを調整することが期待されるため、目的に応じてブロックされます(独自のバッファで十分です)。しかし、RTPソースはリアルタイムでやっているので、HTTPクライアントはオーディオに圧倒されません。

しかし明らかに、何か他のことが起こり、Linux、MacOS、Windows(これらのコードはすべてこのコードで動作します)と2つの異なるネットワークトポロジーでそれを観察しました。

センド()ロングブロックは、私が(送信中と、スレッドブロックを何が起こるかで欠けている何かのように、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

ありがとうございました - この時点でデータを送信するのが目的であるため、スレッドがブロックされていても構いませんが、実際にはパケットが失われ、 。私は、それがソケットごとに変更できるかどうか、そしてどのように変更できるかを投資する必要があります。私はおそらく他のオーディオアプリケーションでこの問題は見られないでしょう。大量のオーディオを事前に送信する可能性があるので、ネットワークのヒックアップは –

+0

です。コメントタイムアウト:-( TCPウィンドウと関連するパラメータが 私が試した2つのネットワークは、私が見ることができるように、信頼できるスーパーではありません.RTP(UDP)側では、私が要求しなければならない多くの紛失したパケットを見ています。再送信 –

+0

SO_SNDBUFを増やしたい場合は、より大きな「漏れバケツ」を提供することでこれを緩和する必要があります。もう1つは、ソケットまたはシステム上のTCP RTO値を減らす方法です(これは** SO_SNDTIMEOではありません - それは違う)RTOは接続が開いたままの状態で調整される動的な値なので、システム設定。 [man 7 tcp](https://linux.die)を試してみてください。net/man/7/tcp)、または "tcp socket change rto"のインターネット検索が可能です。このトピックを読むにはたくさんのことがあります。 – selbie

関連する問題