C# GetResponseStream()或ReadBytes()谁实际负责下载数据以及如何下载?
如果我们创建一个HttpWebRequest并从它的响应中获得ResponseStream,那么数据是否会立即被完全下载,或者,当我们调用流的ReadBytes时,只有数据会从网络下载,然后读取内容 我想参考的代码示例如下所述:C# GetResponseStream()或ReadBytes()谁实际负责下载数据以及如何下载?,c#,.net,system.net.httpwebrequest,C#,.net,System.net.httpwebrequest,如果我们创建一个HttpWebRequest并从它的响应中获得ResponseStream,那么数据是否会立即被完全下载,或者,当我们调用流的ReadBytes时,只有数据会从网络下载,然后读取内容 我想参考的代码示例如下所述: var webRequest = HttpWebRequest.Create('url of a big file approx 700MB') as HttpWebRequest; var webResponse = webRequest.GetResponse();
var webRequest = HttpWebRequest.Create('url of a big file approx 700MB') as HttpWebRequest;
var webResponse = webRequest.GetResponse();
using (BinaryReader ns = new BinaryReader(webResponse.GetResponseStream()))
{
Thread.Sleep(60000); //Sleep for 60seconds, hope 700MB file get downloaded in 60 seconds
//At this point whether the response is totally downloaded or will not get downloaded at all
var buffer = ns.ReadBytes(bufferToRead);
//Or, in the above statement ReadBytes function is responsible for downloading the content from the internet.
}
GetResponseStream
打开并返回一个流
对象。流对象源于底层的套接字
。此套接字
由网络适配器异步发送数据。数据刚刚到达并被缓冲GetResponseStream
将阻止执行,直到第一个数据到达
ReadByte
将数据从套接字层向上拉到c。此方法将阻止执行,直到有一个字节可用为止
过早关闭流将结束异步传输(关闭
套接字,当其连接失败时会通知发送方),并丢弃(刷新)您尚未使用的任何缓冲数据。GetResponseStream
打开并返回流
对象。流对象源于底层的套接字
。此套接字
由网络适配器异步发送数据。数据刚刚到达并被缓冲GetResponseStream
将阻止执行,直到第一个数据到达
ReadByte
将数据从套接字层向上拉到c。此方法将阻止执行,直到有一个字节可用为止
过早地关闭流将结束异步传输(关闭套接字,由于其连接将失败,发送方将收到此通知),并丢弃(刷新)您尚未使用的任何缓冲数据。要回答有关流何时启动的问题,请GetResponseStream()将开始从服务器接收数据。但是,在某个时刻,如果不读取缓冲区,网络缓冲区将变满,服务器将停止发送数据。有关tcp缓冲区等的详细说明,请参阅
因此,你6万次的睡眠对你没有多大帮助,因为一路上的网络缓冲区将被填满,数据将停止到达,直到你读完为止。最好是边读边写
有关ResponseStream工作原理的更多信息。
如果您想知道要使用的缓冲区大小,请参阅 要回答您关于流媒体何时开始的问题,GetResponseStream()将开始从服务器接收数据。但是,在某个时刻,如果不读取缓冲区,网络缓冲区将变满,服务器将停止发送数据。有关tcp缓冲区等的详细说明,请参阅
因此,你6万次的睡眠对你没有多大帮助,因为一路上的网络缓冲区将被填满,数据将停止到达,直到你读完为止。最好是边读边写
有关ResponseStream工作原理的更多信息。
如果您想知道要使用的缓冲区大小,请参阅
好了,我们准备好出发了。如果你把你自己的信息流放上去或贴上去,会有点不同,但区别是相似的
var webResponse = webRequest.GetResponse();
当GetResponse()
返回时,它至少已经读取了所有HTTP头。它可能已经读取了重定向的头,并对重定向到的URI执行了另一个请求。也有可能它实际上正在命中缓存(直接命中或由于Web服务器setnt 304未修改),但默认情况下,该缓存的详细信息对您是隐藏的
套接字的缓冲区中可能还有一些字节
using (BinaryReader ns = new BinaryReader(webResponse.GetResponseStream()))
{
此时,我们得到了一个表示网络流的流
让我们删除Thread.Sleep()
它除了增加连接超时的风险之外,什么都不做。即使假设等待时没有超时,由于您没有读取字节,连接也会“后退”发送字节,因此其效果将比您故意添加减速更慢
var buffer = ns.ReadBytes(bufferToRead);
此时,要么读取bufferToRead
字节以创建byte[]
,要么小于bufferToRead
,因为流的总大小小于该值,在这种情况下buffer
包含整个流。这将花费尽可能长的时间
}
此时,由于执行了成功的HTTP GET,底层web访问层可能会缓存响应(如果响应非常大,则可能不会缓存响应-默认假设是非常大的请求不会多次重复,也不会从缓存中受益)
如果出现错误情况,将引发异常,在这种情况下,将永远不会进行缓存(缓存错误响应没有意义)
没有必要睡觉,或者“等待”它
值得考虑的是,通过直接操作流而不是通过读卡器,以下变体的工作级别略低:
using(var stm = webResponse.GetResponseStream())
{
我们将直接在流上工作
byte[] buffer = new byte[4096];
do
{
int read = stm.Read(buffer, 0, 4096);
这将返回最多4096字节的。它可能读得更少,因为它已经有一块字节可用,并且它会立即返回那么多字节。如果它在流的末尾,它将只返回0个字节,因此这给了我们等待和不等待之间的平衡——它承诺等待足够长的时间以获得至少一个字节,但它是否等待直到获得所有4096个字节,取决于流选择是否更有效地等待那么长的时间或返回更少的字节
DoSomething(buffer, 0, read);
我们用我们得到的字节工作
} while(read != 0);
Read()
}
并且,当流被释放时,响应可以被缓存,也可以不被缓存
正如你所看到的,即使是在最底层.NET也能提供
}