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

Stalled HTTP request (chrome) using own web server

我正在用 C# 编写一个用于教育目的的嵌入式 HTTP 服务器(更多地了解 rfc 并学习一些关于 winsock 的知识)。

现在我可以提供静态网页。服务器本身似乎相当快,但有一个例外。 Chrome 与 IE 相比,加载我的测试页面非常慢。此外,捕获的网络日志显示每个请求都有很大的延迟。

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加载的第一个页面,包括捕获的网络和服务器日志记录:

如您所见,除了第一个请求(因为请求解析器和管道在第一次使用时被初始化)之外,处理得足够快。 IE 在 16 毫秒内收到响应。

现在 Chrome 加载第一页:

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

编辑:Request/Response HTML 页面(第一个 HTTP 请求)

非常感谢任何线索为什么会出现这种行为以及解决它的可能性!

经过更多研究,我找到了这种行为的原因。不知何故 Chrome 需要更长的时间来解析环回适配器主机文件中的主机名。使用 IP 地址而不是 "localhost" 会在 10 毫秒内产生可接受的响应。 使用 HttpListener 时不会发生此行为的原因很简单,即 HttpListener 使用 HTTP API 将 URI 映射到底层套接字来创建 UrlGroups。

经过更多研究,我找到了这种行为的原因。不知何故 Chrome 需要更长的时间来从主机文件中解析环回适配器的主机名。使用 IP 地址而不是 "localhost" 会在 10 毫秒内产生可接受的响应。 使用 HttpListener 时不会发生此行为的原因很简单,即 HttpListener 使用 HTTP API 将 URI 映射到底层套接字来创建 UrlGroups。