1

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.
}
4

3 に答える 3

4

GetResponseStreamオブジェクトを開いて返しStreamます。ストリーム オブジェクトは、基になる から供給されますSocket。これSocketは、ネットワーク アダプターによって非同期的に送信されるデータです。データが到着し、バッファリングされます。GetResponseStream最初のデータが到着するまで実行をブロックします

ReadByteソケット層から C# にデータをプルアップします。このメソッドは、バイトが利用可能になるまで実行をブロックします

ストリームを途中で閉じると、非同期転送が終了し ( を閉じます。接続が失敗するSocket送信者に通知されます)、まだ使用していないバッファリングされたデータはすべて破棄 (フラッシュ) されます。

于 2014-01-22T11:01:57.050 に答える
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、ストリーム全体が含まれています。これにはいくらでも時間がかかります。

}

この時点で、HTTP GET が正常に実行されたため、基盤となる Web アクセス レイヤー応答をキャッシュする可能性があります (おそらく、応答が非常に大きい場合はそうではありません。デフォルトの想定では、非常に大きな要求はあまり繰り返されず、メリットもありません)。キャッシングから)。

エラー条件が発生すると例外が発生し、その場合、キャッシュは実行されません (バグのある応答をキャッシュしても意味がありません)。

眠る必要はありません。そうでなければ、「待つ」必要はありません。

リーダーではなくストリームを直接操作することで、わずかに低いレベルで機能する次のバリアントを検討する価値があります。

using(var stm = webResponse.GetResponseStream())
{

ストリームで直接作業します。

byte[] buffer = new byte[4096];
do
{
    int read = stm.Read(buffer, 0, 4096);

これにより、最大 4096 バイトが返されます。すでに使用可能なバイトのチャンクがあり、すぐにその数を返すため、読み取りが少なくなる場合があります。ストリームの最後にある場合は 0 バイトのみを返すため、これにより、待機することと待機しないことのバランスが取れます。少なくとも 1 バイトを取得するのに十分な時間待機することが約束されていますが、取得するまで待機するかどうかは関係ありません。すべての 4096 バイトは、その長さで待機する方が効率的か、それともより少ないバイトを返す方が効率的かを選択するストリーム次第です。

    DoSomething(buffer, 0, read);

取得したバイトを処理します。

} while(read != 0);

Read()ストリームの最後にある場合は、0 バイトしか返されません。

}

繰り返しになりますが、ストリームが破棄されると、応答がキャッシュされる場合とされない場合があります。

ご覧のように、.NET を使用する場合、最低レベルでも .NET にアクセスできますHttpWebResponse。何かを待機するためのコードを追加する必要はありません。これは常に行われるためです。

ストリームへの非同期アクセスを使用して待機を回避できますが、非同期メカニズムは、利用可能なときに結果を取得することを意味します。

于 2014-01-22T11:34:47.993 に答える
1

ストリーミングの開始時期に関する質問に答えると、GetResponseStream() はサーバーからのデータの受信を開始します。ただし、バッファを読み取らないと、ある時点でネットワーク バッファがいっぱいになり、サーバーはデータの送信を停止します。tcp バッファなどの詳細な説明については、こちらを参照してください。

したがって、60000 のスリープは、途中でネットワーク バッファがいっぱいになり、読み取るまでデータの到着が停止するため、あまり役に立ちません。読み飛ばして、まとめて書き込んでいくとよいでしょう。

ResponseStream の仕組みの詳細については、こちらをご覧ください。使用するバッファ サイズについて疑問がある場合は、こちらを参照してください。

于 2014-01-22T11:12:00.203 に答える