# ASP .NET Core 整体概念推演

## 演化与完善整体概念 <a href="#yan-hua-yu-wan-shan-zheng-ti-gai-nian" id="yan-hua-yu-wan-shan-zheng-ti-gai-nian"></a>

* ASP .NET Core 整体概念推演
* 整体概念推演到具体的形式

### ASP .NET Core 整体概念推演 <a href="#aspnetcore-zheng-ti-gai-nian-tui-yan" id="aspnetcore-zheng-ti-gai-nian-tui-yan"></a>

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2F4UdS3jgzpJ2DMbTwnVxh%2F291.jpg?alt=media\&token=2c3d41b1-5fb9-4450-9575-3bfb7d76fb3a)

ASP .NET Core 其实就是通过 web framework 处理 HTTP 请求并提供 HTTP 响应

web framework 由程序员使用，它包括 ASP .NET Core，Express，spring 等等组成

这样我们就完成了对 ASP .NET Core 的底层建模，接下来对 HTTP 请求和 HTTP 响应进行细化

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FqYxIUMcYCvJs0eShUHoc%2F292.jpg?alt=media\&token=123e4a00-05f2-4f7c-8ac4-479f7e78ecac)

对于原始 HTTP 请求，服务器通过监听配置对 IP 端口进行监听

IP 端口与 Socket 网络建立连接，Socket 网络连接分为 input stream 和 output stream

input stream 接收并转化 HTTP 请求连接（C# 可识别），包括 HTTPContext

HTTP 请求连接经过处理之后生成 output stream

### 整体概念推演到具体的形式 <a href="#zheng-ti-gai-nian-tui-yan-dao-ju-ti-de-xing-shi" id="zheng-ti-gai-nian-tui-yan-dao-ju-ti-de-xing-shi"></a>

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FKN6zLvPHyjnfeq2Gb9cZ%2F293.jpg?alt=media\&token=deadae00-0312-4702-b7d7-4314777a2c4b)

Endpoint 有一个 Options 配置，用于配置 Socket

TransportFactory 分为 SocketTransportFactory 和 LiburyTransportFactory

TransportFactory 绑定 ConnectionListener，ConnectionListener 监听 Socket 请求

基于 Socket 创建 SocketConnection，组成 ConnectionContext

创建之后通过 Start 方法，开始接收发送请求，对应 Socket 网络连接的 output stream 到处理之前的过程

接下来通过源码找到上述的过程：<https://github.com/dotnet/aspnetcore/>

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2F56HN6r0mJo4MtIqSQA6I%2F294.jpg?alt=media\&token=2eb131a6-08cc-4a93-9e13-0e66eb1c1a6a)

在 src/Servers/Kestrel/Kestrel 目录下有一个 WebHostBuilderKestrelExtensions 的扩展方法注入了 KestrelServerImpl

```
services.AddSingleton<IServer, KestrelServerImpl>();
```

KestrelServerImpl 是继承自 IServer 的接口，IServer 是在 Hosting 中的，在 IServer 中有一个 StartAsync 的方法

```
Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) where TContext : notnull;
```

在 KestrelServerImpl 的 StartAsync 方法中我们可以找到一个 OnBind 的方法

```
async Task OnBind(ListenOptions options, CancellationToken onBindCancellationToken)
```

在这个 OnBind 方法中可以看到整个 options 在 ListenOptions 里面，而在 ListenOptions 里面可以看到 EndPoint 属性

```
public EndPoint EndPoint { get; internal set; }
```

监听实际上会被拆解成好几个方法，首先是一个绑定的方法，把 EndPoint 传入到 TransportManager 的绑定方法

```
options.EndPoint = await _transportManager.BindAsync(options.EndPoint, multiplexedConnectionDelegate, options, onBindCancellationToken).ConfigureAwait(false);
```

TransportManager 的绑定方法使用了 TransportFactory 的绑定方法

```
var transport = await _multiplexedTransportFactory.BindAsync(endPoint, features, cancellationToken).ConfigureAwait(false);
```

TransportFactory 是一个 IConnectionListenerFactory，它有两个实现：SocketTransportFactory，LiburyTransportFactory

在 SocketTransportFactory 的绑定方法中会产生一个 SocketConnectionListener 的监听器

```
var transport = new SocketConnectionListener(endpoint, _options, _logger);
```

SocketConnectionListener 是由 SocketConnectionListenerFactory 产生的，SocketConnectionListenerFactory 继承自 IConnectionListenerFactory

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FmD8eB18QO88D7g7DgYRc%2F295.jpg?alt=media\&token=56d67985-e352-444f-ac4b-1d56aaa0ee67)

创建 SocketConnectionListener 监听器之后调用 StartAcceptLoop 方法传入 connectionListener

```
StartAcceptLoop(new GenericConnectionListener(transport), c => connectionDelegate(c), endpointConfig);
```

在 StartAcceptLoop 方法中开始接收

```
var acceptLoopTask = connectionDispatcher.StartAcceptingConnections(connectionListener);
```

在 StartAcceptingConnections 中调用了 listener 的 AcceptAsync 方法接收

```
var connection = await listener.AcceptAsync();
```

SocketConnectionListener 的 AcceptAsync 方法会产生一个 ConnectionContext

```
public ValueTask<ConnectionContext?> AcceptAsync(CancellationToken cancellationToken = default)
```

这个 ConnectionContext 由 SocketConnectionContextFactory 创建

```
return _factory.Create(acceptSocket);
```

Create 方法创建了一个 SocketConnection，这个连接里面有 InputOptions 和 OutputOptions

```
var connection = new SocketConnection(socket,
    _memoryPool,
    setting.Scheduler,
    _logger,
    setting.SocketSenderPool,
    setting.InputOptions,
    setting.OutputOptions,
    waitForData: _options.WaitForDataBeforeAllocatingBuffer);
```

创建之后直接启动，这是一个自启动的过程

```
connection.Start();
```

在 StartAcceptingConnections 得到 SocketConnection 后创建 KestrelConnection，创建之后的转化由 \_connectionDelegate 执行

```
var kestrelConnection = new KestrelConnection<T>(
    id, _serviceContext, _transportConnectionManager, _connectionDelegate, connection, Log);
```

在 KestrelConnection 的执行方法 ExecuteAsync 里面，调用了 \_connectionDelegate

```
await _connectionDelegate(connectionContext);
```

![](https://3083743005-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F8gwpNo3eyzHkX0O40HRA%2Fuploads%2FVGupqqtlVOFxjg6ztVGE%2F296.jpg?alt=media\&token=93799b5e-9fb7-40bb-82cf-c7ce15a3dde6)

接下来全部交给 HttpConnectionMiddleware 处理，看一下如何在 KestrelServerImpl 中构建创建

```
options.UseHttpServer(ServiceContext, application, options.Protocols, addAltSvcHeader);
var connectionDelegate = options.Build();
```

在 UseHttpServer 中创建 HttpConnectionMiddleware

```
var middleware = new HttpConnectionMiddleware<TContext>(serviceContext, application, protocols, addAltSvcHeader);
```

在 HttpConnectionMiddleware 中开启 HttpConnectionContext 的执行

```
var httpConnectionContext = new HttpConnectionContext(
    connectionContext.ConnectionId,
    protocols,
    altSvcHeader,
    connectionContext,
    _serviceContext,
    connectionContext.Features,
    memoryPoolFeature?.MemoryPool ?? System.Buffers.MemoryPool<byte>.Shared,
    localEndPoint,
    connectionContext.RemoteEndPoint as IPEndPoint);
httpConnectionContext.Transport = connectionContext.Transport;

var connection = new HttpConnection(httpConnectionContext);

return connection.ProcessRequestsAsync(_application);
```

在 ProcessRequestsAsync 中开始 requestProcessor 的 Context 的转化协议

```
public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> httpApplication) where TContext : notnull
```

**作业**

在了解完 asp .net core 第2层的架构之后， 从 HttpConnectionMiddleware 开始，把 KestrelConnection 到 HttpContext 的转化过程用OPD 进行细化
