2011-02-24 4 views
1

.NETソケットとNetworkStreamの両方は、利用可能なデータがない場合にブロックするReadメソッドを提供します。問題は、クライアントがメッセージのサイズを知らない場合、サーバーがメッセージの送信を完了したときに信頼できる方法を理解できないことです。HTTPレベルの.NETソケットからの読み取りをいつ終了するかを知る

私の質問は、ソケットからの読み取りを停止し、クライアントに完全なメッセージを表示するために、上位レベルのライブラリ(HTTPレベルのWebRequestなど)はどのような原則を使用していますか? HTTPプロトコルが "EOF"トークンを提供していないようです...

答えて

3

HTTP 1.1は、2つのメカニズムのいずれかを使用してこれを管理します。 content-lengthがヘッダーで送信されるか、またはchunked transfer encodingが使用されます。チャンクされたトランスコーディングエンコーディングは、HTTP 1.0を介したHTTP 1.1の大きな利点の1つです。コンテンツ長が送信されなかった場合、送信の終了を確実に検出することができないため、送信の問題と実際のペイロードの終わりが曖昧になります。場合によっては(HTTP経由のオーディオストリームなど)、コンテンツの長さやその他のエンコーディングは送信の終了を示すかもしれませんが、この場合、クライアントにとってはほとんど重要ではありません。

+0

ありがとう、ちょうど私が必要なもの! – Konstantin

0

HTTPの場合、content-length HTTPヘッダーは、ソケットを閉じることができるときを定義します。

TCPでは、これは任意です。通常、クライアントまたはサーバは、接続が終了することを通知する特別なメッセージを送信します。

1

ソケットにデータが保留中であるかどうかを確認する方法はいくつかあります。 1つは単に各ソケットのPendingプロパティをチェックし、データがある場合はReceiveだけを呼び出すことです。しかし、これは全くうまくスケールされていないので、1度接続するだけでアプリを使用することをおすすめします。

Socket.Select関数はソケットのIListを取ることができ、短時間の後にはこのデータを保留しているソケットだけを含むようにリストを縮小します。ブロックせずに安全に受信を呼び出すことができます。

他の方法が好ましいのは、非同期ソケットAPIを使用することです。 (NetworkStreamのBeginReceiveまたはBeginReadへの呼び出し)。このような場合、呼び出しはブロックされず、呼び出し後もコードの実行を継続できます。データがソケット上で保留中のときに実行される引数として関数を渡します。これは.NETスレッドプール内のバックグラウンドスレッドで処理されるため、前の2つの方法とは異なり、ここでは同時実行性の問題があります。非同期の処理は、Selectのように繰り返しデータをポーリングするのではなく、データがネットワーク上で待機しているときにCPUに通知するために割り込みを使用して、OSのかなり低いレベルで実行されます。

+0

'Socket.Select'はウィンドウ内で' select'呼び出しを使用しませんか? :(それは本当にダムの実装でない限り、それは "繰り返し"をポーリングする必要はありません(これは私が知っている他の言語/ライブラリではありません) –

+0

selectの実装方法はわかりませんが、非同期メソッドではポーリングする必要はありませんが、データが保留中の場合は中断されます。 –

+0

[高速]の場合、選択が正しく使用されていません。 polled - 考えられるのは、ハンドルが読み取り/書き込み/ oobで利用できるようになることです(そのような時間が経過するか、[オプション]タイムアウトが発生した場合や他の方法で中断された場合には呼び出しはブロックされます)。私は 'Begin/End'の提案に同意します。 –

関連する問題