6

私は現在、私が書いたマネージ C# ネットワーク ライブラリをテストしていますが、時折問題に遭遇しました。この問題は、おそらくすべての送信操作の 1% で、networkstream.write() で非常に一貫した (常に 30 ミリ秒以内) 5000 ミリ秒のブロックとして現れます。これはテスト環境で、毎回まったく同じパケット サイズ (2MB) を使用して、すべてローカルで実行されています。クライアント側では、接続されたネットワーク ストリームに次の内容を継続的に書き込みます。

tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length);
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length);

サーバー側では、データを待機する非同期読み取りを使用します。データが表示されたら、すべてのデータが受信されるまで、tcpClientNetworkStream.DataAvailable に対して while ループを使用します。

バッファがいっぱいの場合、 networkstream.write() がブロックされる可能性があることは認識していますが、これが問題である場合、サーバー側でバッファをクリアするより迅速な方法は考えられません (送信および受信バッファ サイズはデフォルトで 8192 バイトです)。 . ブロックが非常に一貫しているという事実は、非常に奇妙に思えます。私が最初に考えたのは、おそらく何らかの形の Thread.Sleep でしたが、プロジェクト全体を検索しても何も表示されませんでした。誰かがこの問題に光を当てるのを助けることができれば、それは大歓迎です.

マルク

追加する編集:問題を解決するように見えるハックは次のとおりです(BlockCopyによる関連するパフォーマンスヒットがありますが):

byte[] bytesToSend = new byte[headerBytes.Length + dataBytes.Length];
Buffer.BlockCopy(headerBytes, 0, bytesToSend, 0, headerBytes.Length);
Buffer.BlockCopy(dataBytes, 0, bytesToSend, headerBytes.Length, dataBytes.Length);
tcpClientNetworkStream.Write(bytesToSend, 0, bytesToSend.Length);

add2 への編集: また、2 つの非同期書き込みを使用して、2 つの間のスレッド シグナルを使用して問題を再現しました。現時点で私が持っている唯一の解決策は、上記の編集のように単一の書き込み操作です。

add3 への編集: OK、別の可能な修正が続きます。連続した書き込みが時折「ブロック」する理由を知りたいと思っています。

BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream);
sendStream.Write(bytesToSend, 0, bytesToSend.Length);
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length);
sendStream.Flush();

add4 への編集: 「add3 への編集」の解決策をさらに広範囲にテストした後、問題は解消されず、発生が送信の約 0.1% に減少するだけです。はるかに優れていますが、解決には程遠いです。PaulF が提案したように、次に非同期読み取りをブロック読み取りに置き換えて、それがソートされるかどうかを確認します。

4

1 に答える 1

2

わかりました、この質問に対する具体的な答えはありませんので、自分で少し結論を出すために最善を尽くします. 私の推測では、この問題は元々、tcp バッファーをクリアするよりも速く満たしていたために発生したものです。バッファーがいっぱいになると、さらにデータを追加しようとする前に不明な待機時間が発生します。この問題は、おそらく同じマシン内でデータを送受信するときに最も顕著になります。.net のデフォルトの読み取りバッファー サイズは 8192 バイトのみであることを覚えておくことが重要です。したがって、はるかに大きなチャンクで書き込む場合は、この読み取りバッファー サイズを 512000 バイトなどの大きなものに増やすことを検討してください。ただし、これ自体が大きなオブジェクトヒープなどのために他の問題を引き起こしますが、それは別の質問に対する議論になる可能性があります。

于 2011-09-16T11:55:40.130 に答える