这几天发现,.Net Core核心中的核心,也就是作为服务器的监听部分,居然用的是Node.Js的LibUv。.Net Core 作为微软最新的一款开源技术栈,其最大的创新就是用KestrelHtppServer构建了自己的专属服务器,取代了传统的IIS作为服务器,也是为了对抗Java Tomcat ,Apache的利器。这款KestrelHtppServer的核心正是 LibUv。
在.Net Core中,当我们构建如下代码:
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup()
.Build();
BuildWebHost(args).Run()这个Run是整个程序启动的关键,也是其宿主WebHost启动监听的开始。
BuildwebHost(args)经过一系列运行,返回WebHost实例,WebHost调用Microsoft.AspNetCore.Hosting类库下面的扩展类WebHostExtensions的方法Run方法。
public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
}
Host.RunAsync()调用了Microsoft.AspNetCore.Hosting.Internal下面的StartAsync。StartAsync通过控制反转取得KeStrelHttpServer的实例。 Server = _applicationServices.GetRequiredService
在TranSport里面会看到我们熟悉的监听类Listener的实例化,绑定,监听。这个过程不是用到.Net 之前提供的监听类TcpListener来监听客户端运行情况,以及返回结果。恰恰相反,它刚好用到的是LivUV。
具体代码以及注解如下:
listener.ListenSocket = listener.CreateListenSocket();//调用LivUv创建一个服务端Socket
socket.Init(Thread.Loop, Thread.QueueCloseHandle);//初始化LivUvLoopHandle,和Server Socket
listener.ListenSocket.Listen(LibuvConstants.ListenBacklog, ConnectionCallback, listener);
ThrowIfErrored(_uv_listen(handle, backlog, cb));//把服务端Socket传递到LibUv,以便回调函数创建客户端,以及服务端Accept
客户端。
acceptSocket = CreateAcceptSocket();//创建客户端Socket
socket.Init(Thread.Loop, Thread.QueueCloseHandle);//无论客户端还是服务端LivUv,Init函数的第一个参数都是Tread[0].Loop,
第二个参数分别为先初始化服务端,后初始化客户端。
listenSocket.Accept(acceptSocket);//listenSocket服务端,acceptSocket客户端。
DispatchConnection(acceptSocket);//当监听到有数据进入,DispatchConnection接收当前客户端传递的数据进行处理。
//DispatchConnection里面有个重要的功能,就是执行.NetCore里面中间件的最里层的匿名Lamada完成NetCore最后的输出。
Listen里面接受了KeStrelHtppServer传递过来的EndPoint,绑定了端口和IP地址。在利用LibUv核心库,完成了整个过程的绑定与监听,以及客户端传来数据的处理。
LivbUV在.Net Core里面实现其实就几个步骤
1.利用LibUV库Init了一个UvLoopHandle(Thread.StartAsync)
2.利用LibUV库Init了一个UvAsyncHandle,UvLoopHandle 在前,AsyncHandle在后。(Thread.StartAsync)
3.利用LibUV库创建了一个套接字Socket,实际上是服务端的 Server用来监听客户端。也是Loop在前,这个Socket在后。(CreateSocket方法)
4.绑定了KeStrelHttpServer传递过来的EndPoint,百年规定IP地址和Port以便监听(CreateSocket方法)。
5.开启LibUV 监听,实际上是把第3,4两步创建的Server套接字,传递到回调函数调用回调函数,创建客户端Socket 。
6..创建客户端Socket ,Loop在 ,客户端Socket在后。
7.保持监听状态,ServerSocket.Accpet(ClientSocket)。
上面的Init ,Listen,Accept调用NativeMethods方法分别如下:
首先引入非托管类库
[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
Init原型如下:
public static extern int uv_tcp_init(UvLoopHandle loop, UvTcpHandle handle);
Listen原型如下
public static extern int uv_listen(UvStreamHandle handle, int backlog, uv_connection_cb cb);
Accept原型如下:
public static extern int uv_accept(UvStreamHandle server, UvStreamHandle client);
Init有重载方法,NetCore里面通过LivUV创建监听客户端的KeStrelServer,总共也就七步。完成了整个KeStrelServer的核心功能。(Java/.NET讨论群:676817308)