在进行网络I / O时是否缓冲了Stream.Read? [英] Is Stream.Read buffered when doing network I/O?

查看:132
本文介绍了在进行网络I / O时是否缓冲了Stream.Read?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我最近做了一些工作,有人告诉我,如果在通过调用.NET的<$之一获得的网络流上执行 Stream.Read c $ c> GetResponseStream 在 WebResponse 或那些被缓冲。

So I was recently doing some work, when somebody told me that if doing a Stream.Read on a network stream that is obtained from calling one of .NET's GetResponseStream on a WebResponse or those are buffered.

他是如果你要在你正在阅读的代码中设置一个断点,你就不会停止网络流量。我发现这很奇怪,但也希望这是真的。这是如何运作的?它是否准确?

He was saying that if you were to put a breakpoint, in the code where you're reading, you wouldn't stop the network traffic. I find that bizzare, but also hoping that it's true. How does that work? Is it even accurate?

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?
   }
}


推荐答案

否, GetResponseStream 返回的Stream对象没有缓冲。

No, the Stream object returned by GetResponseStream is not buffered.

第二部分(关于设置断点)的简短回答是你的合作工人不正确。网络流量将停止,但最终会形成最终,请继续阅读以获取更多详细信息。

Short answer to your second part (about setting a breakpoint) is that your co-worker is incorrect. Network traffic will stop, but eventually, and to describe "eventually", read on for more details.

Bing forSO_RCVBUF, tcp接收窗口大小,vista自动缩放,以获取更一般的信息。

Bing for "SO_RCVBUF", "tcp receive window size", "vista auto scaling", for even more general information.

详细部分

让我们从这开始,这是Windows网络堆栈的文本视图:

Let's start with this, here's a textual view of the Windows networking stack:

++ .NET Network API

++ .NET Network API's

++ --- Winsock DLL(用户模式)

++ --- Winsock DLL (user mode)

++ ------ afd.sys(内核模式)

++ ------ afd.sys (kernel mode)

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

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

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

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

++ --------------- network interface(hal)

++ --------------- network interface (hal)

这是一个粗略的堆栈,掩盖了一些细节,但一般的想法是.NET调用Winsock用户模式dll,然后将大部分实际工作推送到它的堂兄 AFD (辅助功能驱动程序),然后转到tcpip子系统,等等..

This is a rough stack, glossing over some details, but the general idea is that .NET calls into Winsock user-mode dll, which then pushes most of the real work to its cousin AFD (Ancillary Function Driver), onwards to the tcpip sub system, so on ..

AFD 级别,有一个缓冲区,通常介于 8K和64K 之间,但是对于Vista(及更高版本),它也可以扩展。此设置也可以通过注册表设置进行控制( HKLM \SYSTEM\CurrentControlSet \services \AFD \Parameters )。

At the AFD level, there is a buffer, generally between 8K and 64K, but with Vista (and beyond), it can also scale up. This setting can also be controlled by a registry setting(HKLM\SYSTEM\CurrentControlSet\services\AFD\Parameters).

此外,tcpip.sys还有一个缓冲区,类似于AFD的缓冲区。我相信打开套接字时传递* SO_RCVBUF *设置也可以改变它。

In addition, the tcpip.sys also has a buffer, that is similar to AFD's buffer. I believe *SO_RCVBUF* setting passed when opening the socket can change this too.

基本上,当您接收数据时, tcpip.sys on你代表不断获取数据,并告诉发送者它获得了数据( ACK ),并且直到它的缓冲区已满为止。但与此同时, afd.sys 通过询问数据(然后将其复制到自己的缓冲区)来清除 tcpip.sys 缓冲区,因此 tcpip.sys 可以从发件人那里填充更多数据。

Essentially, when you are receiving data, tcpip.sys on your behalf keeps getting data, and keeps the telling the sender that it got the data (ACK's), and does so until its buffers are full. But at the same time, afd.sys is clearing tcpip.sys buffers by asking it for the data (which it then copies into its own buffer), so tcpip.sys can fill more data from the sender.

然后就是你(.NET API调用者),他也在做同样的事情,调用Read()方法并将数据复制到缓冲区中。

And then there's you (the .NET API caller), who is also doing the same, calling the Read() method and copying data into your buffer.

所以,如果你考虑一下,一条256Kb的消息通过网络传输,64K位于 tcpip.sys 缓冲区,64K位于 afd.sys 缓冲区,你在询问一个4K(你的bufferSize变量)块之后设置一个断点,我们正在看128K ACK'ed收到发送回发送方,并且由于 tcpip.sys 缓冲区已满(假设大小为64K)(并且您被调试会话阻止), tcpip.sys 没有选择,只能告诉发送者停止通过网络发送字节,因为它无法足够快地处理它们。

So, if you think about it, a 256Kb message coming over the wire, 64K sitting in the tcpip.sys buffer, 64K sitting in afd.sys buffer, and you set a breakpoint after asking for one 4K (your bufferSize variable) chunk, we're looking at 128K ACK'ed back to the sender as received, and since the tcpip.sys buffer is full (assuming 64K size) now (and you're blocked by your debugging session), tcpip.sys will no have option but to tell the sender to stop sending being bytes over the wire, because it can't process them quick enough.

实际上(即某人不是一个断点!),我见过GC来诱导这种行为。看到一个3秒垃圾收集的情况,让所有操作系统缓冲区都填满。

Practically (i.e. somebody not setting a breakpoint!), I've seen GC to induce such behavior. Seen a case of a 3 second garbage collection that let all the OS buffers fill up.

这篇关于在进行网络I / O时是否缓冲了Stream.Read?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆