Isa*_*aac 8 .net webserver tcp telnet httpclient
我正在实现一个简单的HTTP客户端,它只连接到Web服务器并获取其默认主页.在这里,它很好用:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我从上面的代码中删除下面的行时,程序会在sr.ReadToEnd上阻塞.
req += "Host: www.google.com\r\n";
Run Code Online (Sandbox Code Playgroud)
我甚至用sr.Read替换了sr.ReadToEnd,但它无法读取任何内容.我用Wireshark看看发生了什么:
使用Wireshark http://www.imagechicken.com/uploads/1252514718052893500.jpg捕获的数据包的屏幕截图
如您所见,在我的GET请求之后,Google没有响应并且请求一次又一次地重新传输.我们似乎必须在HTTP请求中指定主机部分.奇怪的部分是我们不.我使用telnet发送此请求并得到了Google的回复.我还捕获了telnet发送的请求,它与我的请求完全相同.
我尝试了很多其他网站(例如雅虎,微软),但结果是一样的.
那么,telnet的延迟是否会导致Web服务器采取不同的行为(因为在telnet中我们实际上是键入字符而不是将它们一起发送到1个数据包中).
另一个奇怪的问题是当我将HTTP/1.0更改为HTTP/1.1时,程序总是在sr.ReadToEnd行上阻塞.我想那是因为Web服务器没有关闭连接.
一种解决方案是使用Read(或ReadLine)和ns.DataAvailable来读取响应.但我不能确定我已阅读所有回复.我如何读取响应并确保HTTP/1.1请求的响应中没有剩余字节?
注意: 正如W3所说,
(我为我的HTTP/1.1请求做了这个).但我没有看到HTTP/1.0这样的事情.使用telnet 发送没有Host头的请求也没有任何问题.
更新:
TCP标记中的推送标志已设置为1.我也尝试过netsh winsock reset来重置我的TCP/IP堆栈.测试计算机上没有防火墙也没有防病毒.实际发送数据包是因为另一台计算机上安装的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";
Run Code Online (Sandbox Code Playgroud)
在所有类型的请求中,如果我省略Host: part,则Web服务器不响应,如果使用Host: part,即使是无效请求(就像上面的请求一样)也会被响应(通过400:HTTP)错误的请求).
nos说主机:他的机器上不需要部件,这使得情况更加奇怪.
Rem*_*eau -2
尝试直接使用 System.Net.WebClient 而不是 System.Net.Sockets.TcpClient:
using System;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
WebClient wc = new WebClient();
Console.WriteLine("[requesting...]");
Console.WriteLine(wc.DownloadString("http://www.google.com"));
Console.WriteLine("[done!]");
Console.ReadKey();
}
}
}
Run Code Online (Sandbox Code Playgroud)