使用自己的Web服务器停止HTTP请求(chrome)

时间:2015-01-19 19:07:59

标签: c# sockets google-chrome internet-explorer

我正在为C#中的教育目的编写嵌入式HTTP服务器(更多地了解rfc并学习有关winsock的内容)。

现在我可以提供静态网页。服务器本身看起来很合理,有一个很好的例外。与IE相比,Chrome加载我的测试页面的速度非常慢。此外,捕获的网络日志显示每个请求的延迟很长。

Web服务器和浏览器在同一台计算机上运行,​​因此应尽量减少网络延迟。

我查看了其他.NET HTTP服务器实现。使用HttpListener的实现没有显示此行为。我发现的套接字实现和我的实现一样慢。 目前我试图找出为什么Chrome与其他浏览器的行为如此不同以及为什么HttpListener不会受此影响(我知道HttpListener使用HTTP API 2.0但我不知道这个API本身是否使用winsock或其他东西)。

我会附上重要的代码来接受,阅读和回复单个请求,以及IE和Chrome的网络日志。

我接受新套接字的当前代码是:

        socket.Listen(10);

        IAsyncResult asyncResult = null;
        while (!token.IsCancellationRequested)
        {
            if (asyncResult == null)
                asyncResult = socket.BeginAccept(null, null);

            if (asyncResult.IsCompleted)
            {
                var acceptedSocket = socket.EndAccept(asyncResult);
                var connection = new HttpServerConnection(acceptedSocket);
                var queue = this.queue;
                queue.Enqueue(connection);
                asyncResult = null;
            }
            else
            {
                Thread.Sleep(5);
            }
        }

接受套接字的队列由另一个后台线程处理。监听器等待,直到使用socket.Poll(1000, SelectMode.SelectRead);从套接字读取数据(因为Chrome打开多个连接到HTTP服务器,理论上加速页面加载)。

在服务器处理请求之后,使用以下命令发送响应:

         var response = context.Response;
        var connection = context.Connection;

        byte[] buffer;
        using (var stream = new MemoryStream(1024))
        {
            using (var writer = new StreamWriter(stream, Encoding.ASCII, 1024, true))
            {
                writer.Write(HttpVersion.Http11.ToString());
                writer.Write(" ");
                writer.Write((int)response.Status);
                writer.Write(" ");
                writer.WriteLine(response.StatusDescription ?? response.Status.ToString());

                foreach (var httpHeader in response.Headers)
                {
                    writer.Write(httpHeader.Key);
                    writer.Write(": ");
                    writer.WriteLine(httpHeader.Value());
                }

                if (response.Content != null)
                    writer.WriteLine();
            }

            if (response.Content != null)
                response.Content(context, stream);

            stream.Position = 0;

            buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
        }

        connection.Send(buffer);

IE首页加载,包括捕获的netword和服务器日志记录: IE network log

server log 如您所见,除了第一个请求(因为请求解析器和管道在第一次使用时已初始化),处理速度足够快。 IE在16ms内收到回复。

现在Chrome首页加载: Chrome network log

Server log

服务器处理响应的速度与来自IE的响应一样快,但每次请求Chrome需要大约300毫秒。

编辑:HTML页面的请求/响应(第一个HTTP请求) Request/Response for index.html

非常感谢有这种行为和解决问题的可能性的任何线索!

经过一些研究后,我发现了这种行为的原因。不知何故,Chrome需要更长的时间来从环回适配器的主机文件中解析主机名。使用IP地址而不是“localhost”会在10ms内产生可接受的响应。 如果使用HttpListener,则不会发生此行为的原因是HttpListener使用HTTP API创建UrlGroups以将URI与底层套接字映射。

1 个答案:

答案 0 :(得分:0)

经过一些研究后,我发现了这种行为的原因。不知何故,Chrome需要更长的时间来从环回适配器的主机文件中解析主机名。使用IP地址而不是“localhost”会在10ms内产生可接受的响应。 如果使用HttpListener,则不会发生此行为的原因是HttpListener使用HTTP API创建UrlGroups以将URI与底层套接字映射。