问题概述:我已经开始尝试编写自定义HTTP服务器应用程序一段时间了。我发现当任何网络浏览器连接到我的服务器应用程序时,在处理请求之前会有0.5-1秒的“延迟”(根据Google Chrome的说法)(这需要几毫秒)。
我最终尝试制作一个虚拟程序来找出问题所在:
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SlowHTTPServer
{
class FailServer
{
static void Main()
{
//Create socket object, bind it, listen to 80
Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenerSocket.Bind(new IPEndPoint(IPAddress.Any, 80));
listenerSocket.Listen(64);
while (true)
{
Socket clientConn = listenerSocket.Accept(); //Accept
System.DateTime startTime = System.DateTime.Now;
byte[] buffer = new byte[1024]; //Request header buffer
clientConn.Receive(buffer); //Recieve request header
string reqHeader = Encoding.ASCII.GetString(buffer); //Get the string version of it
//We completely ignore most of the request header lol
//Normally i'd send a response header but...
if (reqHeader.IndexOf("script1") != -1) //script1.js - document.title='hai dere'
clientConn.Send(Encoding.ASCII.GetBytes("document.title='hai dere';"));
else if (reqHeader.IndexOf("script2") != -1) //script2.js - Get a pretty background color onload
clientConn.Send(Encoding.ASCII.GetBytes("window.onload=function(){document.body.style.backgroundColor='#FF99FF';};"));
else if (reqHeader.IndexOf("iframe") != -1) //Noob iframe that just has text.
clientConn.Send(Encoding.ASCII.GetBytes("blargh zargh nargh dargh pikachu tangerine zombie destroy annihilate"));
else //hai dere is the body.innerHTML, load script1.js and script2.js
clientConn.Send(Encoding.ASCII.GetBytes("<html><head><script src='script1.js'></script><script src='script2.js'></script></head><body>mainPage<iframe src='iframe.html'>u no haz iframe</iframe></body></html>"));
clientConn.Close(); //Close the connection to client. We've done such a good job!
System.Console.WriteLine((System.DateTime.Now - startTime).TotalMilliseconds);
}
}
}
}
…我现在完全困惑了,因为上面的程序将在2秒钟的时间跨度内为Web浏览器提供page+script+iframe服务[从本地主机连接到本地主机,Windows防火墙+防病毒软件关闭]。使用像Apache这样的服务器,这些请求(当然是在文件系统中使用预先创建的文件)可以在不到100毫秒的时间内得到处理。
从我所看到的,我发布的代码是一个非常精简的HTTP服务器。如果我发送或不发送响应头,性能不会改变。
当我有30多个javascript脚本文件的项目时,这个问题变得非常烦人,页面需要20多秒才能完全加载[当脚本都是10 KB时,这是不可接受的]
如果您查看脚本,您会注意到我跟踪套接字何时接受和何时关闭,通常处理时间仅为1-10毫秒,这意味着在HTTP服务器和Web浏览器之间存在延迟[在接受连接之前]?]
我受不了了,需要帮助。
谢谢。
其他注释:
-我编写的“真正的”服务器接受客户机连接,并将它们传递给另一个线程来完成这项工作,因此发送字节和关闭连接的任务并不是造成如此大延迟的原因。
-绑定到端口80,以测试代码运行程序并导航到
http://127.0.0.1/
或
http://localhost/
图像:
Chrome's developer tools showing the load times
附加程序:
我试图通过创建一个非常简单的服务器/客户端程序来模拟这个问题…问题没有重现,连接时间是1毫秒。我又被难住了
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace SlowSocketAccept
{
class Program
{
static DateTime connectionBeginTime;
static bool listening = false;
static void Main(string[] args)
{
new Thread(ClientThread).Start();
Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenerSocket.Bind(new IPEndPoint(IPAddress.Any, 80));
listenerSocket.Listen(80);
listening = true;
Socket newConn = listenerSocket.Accept();
byte[] reqHeader = new byte[1024];
newConn.Receive(reqHeader);
newConn.Send(Encoding.ASCII.GetBytes("Response Header\r\n\r\nContent"));
newConn.Close();
Console.WriteLine("Elapsed time: {0} ms", (DateTime.Now - connectionBeginTime).TotalMilliseconds);
}
static void ClientThread()
{
while (listening == false) ; //Busy wait, whatever it's an example
System.Threading.Thread.Sleep(10); //Wait for accept to be called =/
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connectionBeginTime = DateTime.Now;
s.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80));
s.Send(Encoding.ASCII.GetBytes("Request Header"));
byte[] response = new byte[1024];
s.Receive(response);
}
}
}
[A和B是螺纹]
a)启动螺纹“B”
b)忙碌等待,直到A设置一个标志表示可以连接
a)创建套接字,开始监听80,设置一个标志告诉b可以连接
b)创建套接字,存储当前时间,并连接到127.0.0.1:80[本地主机:80]
a)线程接受连接并开始侦听
b)线程发送一个虚拟字符串[我们的请求头]
a)接受虚拟字符串,然后将虚拟字符串发回[响应头+内容]
a)紧密连接
经过的时间大约是1毫秒=/