使用自己的 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。
我正在用 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加载的第一个页面,包括捕获的网络和服务器日志记录:
现在 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。