目录
- 目标
- 源码
目标
理解 KestrelServer 如何接收网络请求,网络请求如何转换成 http request context(C# 可识别)
源码
https://github.com/dotnet/aspnetcore/
在目录 aspnetcore\src\Servers\Kestrel\Core\src\Internal 下有一个 KestrelServerImpl
internal class KestrelServerImpl : IServer
在 host 启动的时候调用了 server 的 startup 方法,可以从这个入口开始
public async Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken) where TContext : notnull
StartAsync 方法主要分为以下三步
async Task OnBind(ListenOptions options, CancellationToken onBindCancellationToken)
{
...
}
AddressBindContext = new AddressBindContext(_serverAddresses, Options, Trace, OnBind);
await BindAsync(cancellationToken).ConfigureAwait(false);
BindAsync 方法中使用 AddressBindContext 进行绑定
await AddressBinder.BindAsync(Options.ListenOptions, AddressBindContext!, cancellationToken).ConfigureAwait(false);
在 AddressBinder 的 BindAsync 方法中创建了多种策略进行绑定
var strategy = CreateStrategy(
listenOptions.ToArray(),
context.Addresses.ToArray(),
context.ServerAddressesFeature.PreferHostingUrls);
...
await strategy.BindAsync(context, cancellationToken).ConfigureAwait(false);
例如 AddressesStrategy,它有自己的一个绑定方法
private class AddressesStrategy : IStrategy
{
protected readonly IReadOnlyCollection<string> _addresses;
public AddressesStrategy(IReadOnlyCollection<string> addresses)
{
_addresses = addresses;
}
public virtual async Task BindAsync(AddressBindContext context, CancellationToken cancellationToken)
{
foreach (var address in _addresses)
{
var options = ParseAddress(address, out var https);
context.ServerOptions.ApplyEndpointDefa