Sockets C#插座性能?等待服务器响应时出现的问题

Sockets C#插座性能?等待服务器响应时出现的问题,sockets,c#-4.0,Sockets,C# 4.0,我目前对以下内容有点好奇: 当试图从服务器请求页面时,通常需要几秒钟的时间,可以通过webbrowser或w/e进行确认 我尝试使用套接字执行此操作: string pData = "GET / HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64;

我目前对以下内容有点好奇:

当试图从服务器请求页面时,通常需要几秒钟的时间,可以通过webbrowser或w/e进行确认

我尝试使用套接字执行此操作:

            string pData = "GET / HTTP/1.1\r\n" +
                       "Host: www.google.com\r\n" +
                       "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1\r\n" +
                       "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
                       "Accept-Language: en-us,en;q=0.5\r\n" +
                       "Accept-Encoding: deflate\r\n" +
                       "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" +
                       "Keep-Alive: 115\r\n" +
                       "Connection: keep-alive\r\n\r\n";
        string[] a = CreateSocketRequest("www.google.com", 80, pData, 4);
        Console.WriteLine(a[0] + "\r\n" + a[1]);
注意:对CreateSocketRequest的调用返回一个字符串数组,其标题在索引0中,内容在索引1中。而且,它背后的代码工作得非常好

无论如何,上述请求包的有趣之处在于,当发出请求时,似乎没有响应,实际上,需要暂停调试一段时间,然后恢复程序,以便看到写入控制台的响应

所以我花了几个小时才找到凶手:

HTTP/1.1
在我所有的惊讶和所有的时间浪费中,例如,有人需要将其更改为:

HTTP/1.0
瞧,响应几乎立即写入控制台,没有延迟,什么都没有,就像它应该工作一样

我的问题是:为什么在头文件中使用HTTP/1.1会花费如此长的时间,而HTTP/1.0会立即使用它?如果有人能解释一下这件事,或者至少给我指出正确的方向,我将不胜感激

注意1:我忘了提一下,但是,使用TcpClient和NetworkStream发出相同的请求会导致相同的性能低下,但WebClient会立即执行(没有使用HttpWebRequest进行测试)

注意2:CreateSocketRequest方法(不完整,但这应该能让您大致了解):


我无法找到
CreateSocketRequest
,但使用
HttpWebRequest
时,我能够在0.145秒内得到响应:

HTTP Protocol Version: 1.1

Headers: Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Date: Tue, 05 Jul 2011 06:16:09 GMT
Expires: -1
Set-Cookie: PREF=ID=4bd33e8b133134b4:FF=0:TM=1309846569:LM=1309846569:S=ZT2NPRNq
yYBcgSmY; expires=Thu, 04-Jul-2013 06:16:09 GMT; path=/; domain=.google.com,NID=
48=VwNz5I8Y_Pf51hGWUE38wq1YNb5-OOkPD-9V36tXHkLtitJea8pyO6MLB-wm6lpRmLDyDIiNuoklC
SldpfXFqNWKeKM6P4hIXudtUsEHiMiRICNf5ZUOmQbz1htShb8G; expires=Wed, 04-Jan-2012 06
:16:09 GMT; path=/; domain=.google.com; HttpOnly
Server: gws
X-XSS-Protection: 1; mode=block
Transfer-Encoding: chunked


Duration: 0.145 seconds
代码如下所示:

static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com:80/");
    Console.WriteLine("HTTP Protocol Version: " + request.ProtocolVersion + "\n");

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Console.WriteLine("Headers: \n" + response.Headers);
    sw.Stop();

    Console.WriteLine("Duration: {0} seconds", sw.ElapsedMilliseconds / 1000.0);
    Console.ReadKey();
}

正如我所说,我在任何.NET 4.0库中都找不到方法
CreateSocketRequest
,因此如果这是您编写的方法,请提供它的代码。如果这是另一个图书馆的东西,我不知道我是否能帮你很多。此外,我没有仔细阅读您在请求中提供的所有标题,但我假设其中没有任何特定的内容会导致延迟。

您是对的,CreatSocketRequest是我创建的一个方法,在.NET库中找不到,很抱歉没有说清楚(代码请参阅主要帖子)。无论如何,我看到您已经用HttpWebRequest对其进行了测试,结果是即时的。但我这里的问题是,为什么HTTP/1.1在套接字、TcpClient和NetworkStream上速度如此之慢?而其他一切都能在HttpWebRequest和WebClient上完美运行?这就是困扰我的问题。Lith,我没有时间测试你的代码,但我可以向你保证它与HTTP/1.1无关;还要注意,
Socket.Receive
是一个阻塞调用。我的示例也使用HTTP 1.1,速度一点也不慢。问题是使用Socket类Socket.Receive时阻塞的时间太长。例如,当我使用HTTP/1.1发送GET请求时,它需要大约3分钟的时间才能最终将响应写入控制台(注意:暂停调试时,您会看到它挂起在Socket.Receive,正如您所说,我所知道的,因为这是一个阻塞调用)。但是,当所有的东西都被接收到时,为什么它不结束阻塞呢?奇怪的是,当使用HTTP/1.0时,is不会阻塞3分钟,响应会立即写入控制台。此外,您的示例使用了HttpWebRequest,我有一些程序在使用HTTP/1.1的站点上使用HttpWebRequest和WebClient类,它们都表现得非常出色。我也测试过你的代码,它按照你说的那样工作,我也知道这一点。但是,例如,在Google上使用带有HTTP/1.1的Socket类时,所有这些都会失败,而HTTP/1.0则不会。如果你愿意,我甚至可以创建一个视频来显示我的意思。你必须手动结束通话,因为插座不知道何时收到所有信息。套接字只知道它已经连接到另一个端点,并且它将接收/发送字节。套接字无法知道它应该接收多少字节,这就是为什么HTTP协议在向您发送头时指定内容长度,因此用户负责从套接字请求多少字节。一旦收到所有字节,就不要再次调用Socket.receive,因为它将无限期地阻塞!
static void Main(string[] args)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.google.com:80/");
    Console.WriteLine("HTTP Protocol Version: " + request.ProtocolVersion + "\n");

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Console.WriteLine("Headers: \n" + response.Headers);
    sw.Stop();

    Console.WriteLine("Duration: {0} seconds", sw.ElapsedMilliseconds / 1000.0);
    Console.ReadKey();
}