我试图在不使用第三方库的情况下用C#编写高性能的HTTP服务器,在阅读期间,我在nginx博客上找到了这篇文章。上面提到的正在使用SO_REUESEPORT,但是该选项在.NET套接字和Windows中均不可用,因此我搜索了该选项的替代方法,并且我已经阅读到Windows和.NET均可用的SO_REUSEADDR是我选择的选项有寻找。
我试图通过创建4个套接字并在绑定套接字并开始侦听之前启用重用地址来实现这一点,但是之后发生的事情是只有一个套接字接受连接,即使其线程繁忙。
static readonly byte[] Response = Encoding.ASCII.GetBytes("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r");
static int s_ListenerIndex = 0;
static void Main(string[] args)
{
var listenAddress = new IPEndPoint(IPAddress.Any, 26000);
var sockets = new Socket[4];
Console.WriteLine("Creating sockets");
for (int i = 0; i < sockets.Length; i++)
{
sockets[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sockets[i].SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sockets[i].Bind(listenAddress);
}
Console.WriteLine("Starting listener threads");
for (int i = 0; i < sockets.Length; i++)
{
var socket = sockets[i];
CreateThread(() => ListenSocket(socket));
}
Thread.Sleep(Timeout.Infinite);
}
static void ListenSocket(Socket socket)
{
var listenerId = Interlocked.Increment(ref s_ListenerIndex);
socket.Listen(100);
Console.WriteLine($"Socket #{listenerId} is listening");
while (true)
{
Socket client = socket.Accept();
Console.WriteLine($"Socket #{listenerId} accepted connection");
client.Send(Response);
client.Close();
}
}
static void CreateThread(ThreadStart threadStart)
{
var thread = new Thread(threadStart);
thread.IsBackground = true;
thread.Start();
}
我是在做错什么,还是Windows和.NET无法完成整个技巧?
在Windows上,SO_REUSEADDR选项没有用于HTTP服务器的用例。唯一真正的用例是将数据传递到绑定在同一端口上的所有套接字的多播套接字。
我建议这篇SO帖子进行深入讨论。SO_REUSEADDR和SO_REUSEPORT有何区别?
在带有IOCP的Windows下,您不需要等效的Linux / Unix,它可以在多个线程之间提供负载平衡。IOCP会为您解决这个问题。实现方式有很大不同,但是实现了相同的高度可扩展的结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句