GetRequestStream(またはBeginGetRequestStream)を呼び出す前にContentLengthプロパティを設定してから、そのストリームに書き込むバイト数を減らします。リクエストストリームを取得した後でContentLengthを設定しようとすると、ContentLengthがスローされます。ContentLengthを設定しない場合、HttpWebRequestは、ストリームが閉じられるまでヘッダーをバッファリングして、ContentLengthを適切に設定できるようにします(または、SendChunkedを使用できますが、ここでは機能しません)。これを最大限に制御したい場合は、不正な要求を1つか2つ手動で作成してから、サーバーのポート80へのソケットを開き、要求をTCPストリームに書き込んでから、応答を読み取り、接続をチェックして、閉じられているかどうかを確認します。 。
ただし、このテストは良い考えではないと思います。ここに問題があります:
クライアントはサーバーにリクエストを送信します。コンテンツは100バイトになると主張しています。次に、90バイトを送信し、送信を停止して、接続を開いたままにします。サーバーは90バイトを読み取り、クライアントが100バイトが送信されると言ったため、残りを待ちます。ここで、クライアントは2番目の要求を送信します。サーバーは新しいリクエストの最初の10バイトで何をしますか?
答えは、サーバーはそれらのバイトが前のリクエストの一部であると想定し、それらをそのように扱い、開始から10バイト後に「新しい」リクエストの読み取りを開始することです。これにより、明らかに不正な形式のヘッダーが生成されます。サーバーはそれを気に入らないので、4xxエラーを送信してから、接続を閉じます。接続を閉じる理由は、接続に送信されているデータが何を意味するのかを知る方法がなく、回復する方法がないためです。また、接続の切断は正常ではなく、突然であり、2番目の要求(またはキューに入れられている場合は3番目または4番目)を送信しているもう一方の端のHttpWebRequestは、WebExceptionをスローします。基になる接続が閉じられたため、理由を推測できます。
これと同じ動作により、Expect 100-continueヘッダーで接続が閉じられ、サーバーは、Authが必要な場合など、100-continueの後に4xxを返します。要求が拒否された場合でも、100-continueを送信してそれらのバイトを受信することを確約しているため、次のバイトは同じ要求の一部であると想定する必要があります。そのリクエストを処理しない場合、またはクライアントがリクエストをキャンセルして新しいリクエストを送信する場合(おそらく認証資格情報を使用)、接続を閉じて新しいものを開く必要があります。
最後に、TCPを使用してネットワークストリームからEndOfStreamExceptionをテストしても、私にはまったく意味がありません。TCPはストリームの「終了」をマークせず、ソケットに書き込まれるときにデータを送信し続けます。そのための「EOF」はなく、予想されるデータの量がわからない限り、データがすべて送信されたかどうかを検出する方法はありません。TCPは、接続が閉じられていない限り、実際にはストリームの「終了」を持っていません。閉じられている場合、スタックのどこで操作しているかに応じて、WebExceptionまたはSocketExceptionが発生します。プロトコルの送信エラーはすべてwinsockで処理されます。これ以上データが送信されない場合、接続の一方の端が最終的にもう一方の端にキープアライブを送信して、接続が実際に開いたままであり、一方のホストがデータをドロップしただけではないことを確認します。キープアライブがタイムアウトすると、接続が閉じられ、次にWebExceptionから読み取ろうとしたときにWebExceptionが発生する可能性があります。これらすべてがどのように機能するかを考えると、このテストからどのように価値を得るのかわかりません。不正な形式のリクエストを送信し、それに応じてエラーが処理され、適切な4xxメッセージがクライアントに返送され、接続が適切に閉じられていることを確認する方がはるかに優れています。