如果我们创建一个HttpWebRequest并从其响应中获取ResponseStream,那么数据是否会立即完全下载,或者当我们调用流的ReadBytes时,只有数据将从网络下载然后读取内容?
我想参考的代码示例如下:
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.
}
答案 0 :(得分:4)
GetResponseStream
会打开并返回Stream
个对象。流对象来自底层Socket
。此Socket
由网络适配器异步发送数据。数据刚到达并被缓冲。 GetResponseStream
将阻止执行,直到第一个数据到达。
ReadByte
将数据从套接字层提取到c#。 此方法将阻止执行,直到有一个字节可用。
过早关闭流将结束异步传输(关闭Socket
,发件人将收到通知,因为他们的连接将失败)并丢弃(刷新)任何缓冲的数据你还没有用过。
答案 1 :(得分:3)
var webRequest = HttpWebRequest.Create('url of a big file approx 700MB') as HttpWebRequest;
好的,我们准备好了。如果您对自己的流进行PUT或POST,情况会有所不同,但差异是类似的。
var webResponse = webRequest.GetResponse();
当GetResponse()
返回时,它至少会读取所有HTTP标头。它可能已经读取了重定向的标头,并对重定向到的URI执行了另一个请求。它也可能实际上是在点击缓存(直接或因为webserver setnt 304 Not Modified),但默认情况下会隐藏你的详细信息。
套接字缓冲区中可能会有更多字节。
using (BinaryReader ns = new BinaryReader(webResponse.GetResponseStream()))
{
此时,我们已经有了代表网络流的流。
让我们删除Thread.Sleep()
它除了增加连接超时风险外什么都不做。即使假设它在等待时没有超时,连接也会退出"从发送字节起,因为你没有阅读它们,所以效果将比你通过添加故意放慢速度更慢。
var buffer = ns.ReadBytes(bufferToRead);
此时,已读取bufferToRead
字节以创建byte[]
或小于bufferToRead
,因为流的总大小小于buffer
,在这种情况下{ {1}}包含整个流。这需要花费的时间。
}
此时,由于执行了成功的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使我们能够在使用HttpWebResponse
时访问,也无需添加代码来等待任何事情,因为这总是为我们完成。
您可以使用对流的异步访问来避免等待,但异步机制仍然意味着您可以获得结果。
答案 2 :(得分:1)