Web サーバーに接続してデフォルトのホームページを取得する単純な HTTP クライアントを実装しています。ここにあり、うまく機能します:
using System;
using System.Net.Sockets;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TcpClient tc = new TcpClient();
tc.Connect("www.google.com", 80);
using (NetworkStream ns = tc.GetStream())
{
System.IO.StreamWriter sw = new System.IO.StreamWriter(ns);
System.IO.StreamReader sr = new System.IO.StreamReader(ns);
string req = "";
req += "GET / HTTP/1.0\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";
sw.Write(req);
sw.Flush();
Console.WriteLine("[reading...]");
Console.WriteLine(sr.ReadToEnd());
}
tc.Close();
Console.WriteLine("[done!]");
Console.ReadKey();
}
}
}
上記のコードから以下の行を削除すると、プログラムはsr.ReadToEndでブロックされます。
req += "Host: www.google.com\r\n";
sr.ReadToEndをsr.Readに置き換えましたが、何も読み取れません。Wireshark を使用して、何が起こっているかを確認しました。
Wireshark を使用してキャプチャされたパケットのスクリーンショット http://www.imagechicken.com/uploads/1252514718052893500.jpg
ご覧のとおり、GET リクエストの後、Google は応答せず、リクエストは何度も再送信されます。HTTP リクエストでHost部分を指定する必要があるようです。奇妙な部分は、WE DON'T です。telnetを使用してこのリクエストを送信すると、Google から応答がありました。telnet から送信されたリクエストもキャプチャしましたが、それは私のリクエストとまったく同じでした。
他の多くの Web サイト (Yahoo、Microsoft など) も試しましたが、結果は同じです。
では、telnet の遅延によって Web サーバーの動作が異なるのでしょうか (telnetでは、文字を 1 つのパケットにまとめて送信するのではなく、実際に入力するため)。
別の奇妙な問題は、HTTP/1.0をHTTP/1.1に変更すると、プログラムが常にsr.ReadToEnd行でブロックされることです。これは、Web サーバーが接続を閉じていないためだと思います。
1 つの解決策は、Read (またはReadLine ) とns.DataAvailableを使用して応答を読み取ることです。しかし、すべての回答を読んだかどうかはわかりません。応答を読み取って、HTTP/1.1 要求の応答にバイトが残っていないことを確認するにはどうすればよいですか?
注: W3 が言うように、
Host request-header フィールドは、すべての HTTP/1.1 リクエストに付随する必要があります 。
(そして、HTTP / 1.1リクエストに対してそれを行いました)。しかし、 HTTP/1.0ではそのようなことは見たことがありません。また、telnet を使用してHostヘッダーなしでリクエストを送信しても、問題なく動作します。
アップデート:
TCP セグメントでプッシュフラグが 1 に設定されています。TCP/IP スタックをリセットするためにnetsh winsock resetも試しました。テスト コンピューターには、ファイアウォールもウイルス対策もありません。別のコンピュータにインストールされた Wireshark がパケットをキャプチャできるため、パケットは実際に送信されます。
また、他のリクエストもいくつか試しました。例えば、
string req = "";
req += "GET / HTTP/1.0\r\n";
req += "s df slkjfd sdf/ s/fd \\sdf/\\\\dsfdsf \r\n";
req += "qwretyuiopasdfghjkl\r\n";
req += "Host: www.google.com\r\n";
req += "\r\n";
すべての種類のリクエストで、Host:の部分を省略した場合、Web サーバーは応答しません。また、 Host : の部分を省略した場合、無効なリクエスト (上記のリクエストと同様) でさえ応答されます (400: HTTP によって)。要求の形式が正しくありません)。
nosはHost:の部分は彼のマシンでは必要ないと言っており、これが状況をより奇妙にしています。