3

だから私は最近いくつかの仕事をしていました、誰かが私にStream.Read、.NETの1つを呼び出すことから得られたネットワークストリームで行うとGetResponseStreamWebResponseまたはそれらがバッファリングされると言ったとき。

彼は、あなたが読んでいるコードにブレークポイントを置くとしたら、ネットワークトラフィックを止めないだろうと言っていました。私はその奇妙なことを見つけましたが、それが真実であることも望んでいます。それはどのように機能しますか?それも正確ですか?

using (Stream webResponseStream = this.webResponse.GetResponseStream())
{
   byte[] readBuffer = new byte[bufferSize];
   int bytesRead = webResponseStream.Read(readBuffer, 0, bufferSize);
   while (bytesRead > 0)
   {
        bytesRead = webResponseStream.Read(readBuffer, 0, bufferSize);
        // If I put a breakpoint here, does network activity stop?
   }
}
4

3 に答える 3

5

いいえ、GetResponseStreamによって返されるStreamオブジェクトはバッファリングされません。

2番目の部分(ブレークポイントの設定について)に対する簡単な答えは、同僚が正しくないということです。ネットワークトラフィックは停止しますが、最終的には、「最終的に」説明するために、詳細を読んでください。

さらに一般的な情報については、「SO_RCVBUF」、「tcp受信ウィンドウサイズ」、「vista自動スケーリング」のBingを参照してください。

詳細部

これから始めましょう。これがWindowsネットワークスタックのテキストビューです。

++.NETネットワークAPI

++ --- Winsock DLL(ユーザーモード)

++ ------ afd.sys(カーネルモード)

++ --------- tcpip.sys

++ ------------ ndis

++ ---------------ネットワークインターフェース(hal)

これは大まかなスタックであり、いくつかの詳細をざっと見ていますが、一般的な考え方は、.NETがWinsockユーザーモードdllを呼び出し、実際の作業のほとんどをそのいとこであるAFD(Ancillary Function Driver)にプッシュし、さらにtcpipsubにプッシュすることです。システムなど..

AFDレベルでは、通常8K〜64Kのバッファーがありますが Vista(およびそれ以降)では、スケールアップすることもできます。この設定は、レジストリ設定( HKLM \ SYSTEM \ CurrentControlSet \ services \ AFD \ Parameters )によっても制御できます。

さらに、tcpip.sysには、AFDのバッファーと同様のバッファーもあります。ソケットを開くときに渡される*SO_RCVBUF*設定も、これを変更できると思います。

基本的に、データを受信して​​いるとき、あなたに代わってtcpip.sysはデータを取得し続け、送信者にデータ( ACK)を取得したことを通知し続け、バッファーがいっぱいになるまでそうします。ただし、同時に、afd.sysはデータを要求することでtcpip.sysバッファーをクリアしているため(データは独自のバッファーにコピーされます)、tcpip.sysは送信者からより多くのデータを入力できます。

そして、あなた(.NET API呼び出し元)も同じことをしていて、Read()メソッドを呼び出して、データをバッファーにコピーしています。

したがって、考えてみると、256Kbメッセージがネットワーク経由で送信され、64Kがtcpip.sysバッファーにあり、64Kがafd.sysバッファーにあり、1つの4K(bufferSize変数)チャンクを要求した後にブレークポイントを設定します。受信時に送信者に返される128KACKを確認していますが、tcpip.sysバッファーがいっぱいになっているため(64Kサイズを想定)、デバッグセッションによってブロックされているため、tcpip.sysにはオプションがありません。ただし、送信者にバイトを介した送信を停止するように指示します。これは、送信者が十分な速度で処理できないためです。

実際には(つまり、誰かがブレークポイントを設定していない!)、GCがそのような動作を誘発するのを見てきました。すべてのOSバッファがいっぱいになる3秒のガベージコレクションのケースが見られます。

于 2012-01-20T07:46:46.687 に答える
2

This is accurate. TCP is implemented by the Windows TCP/IP driver stack. Setting a breakpoint in your program does not stop the driver from downloading data from the server. Not until the driver decides that too much kernel pool space is being used to buffer the data. The exact rules for which are undocumented.

This is an optimization, a standard one in operating systems. The strategy makes TCP transfers very efficient, it isn't paced by how responsive your program is, only by the bandwidth of the connection and how responsive the driver stack is to network card interrupts. Which it is very good at, it is a driver's job.

于 2012-01-20T02:10:37.373 に答える
0

デフォルトでは NetworkStream はバッファリングされませんこのストリームを読み取っているプロシージャ内にブレークポイントを配置すると、基になるソケットにデータを送信しているクライアントはブロックされ、リモート ソケットが再び受信できるようになるまで待機します。クライアントはソケットに書き込むことができないため、ネットワーク トラフィックが停止します。

これは、 BufferedStreamクラスを使用してバッファリングする方法を示すブログ投稿です。

于 2012-01-19T22:57:23.887 に答える