C# - Kestrelのお世話になるTCPサーバー


ASP.NET Core 付属の Kestrel は Web的な機能だけでなく、ただの TCP 接続も外から扱えるようになっている。
そのときに使うのがConnectionHandler

ベンチマークによれば、ASP.NET Core は接続さばいて応答するのは速いらしいので乗っかれると良いのでは?と思った。

ほとんど上記リンク先のコピペだが、
ConnectionHandlerを継承したクラスを用意して

public class EchoConnectionHandler : ConnectionHandler
{
    public override async Task OnConnectedAsync(ConnectionContext connection)
    {
        Console.WriteLine("Connected .");

        while (true)
        {
            var recv = await connection.Transport.Input.ReadAsync();

            foreach (var data in recv.Buffer)
            {
                await connection.Transport.Output.WriteAsync(data);
            }

            if (recv.IsCompleted)
            {
                break;
            }

            connection.Transport.Input.AdvanceTo(recv.Buffer.End);
        }

        Console.WriteLine("DisConnected .");
    }
}

Kestrel 設定の中で、用意したハンドラを登録する。

Host.CreateDefaultBuilder(args)
.ConfigureWebHost(builder =>
{
    builder.UseKestrel(options =>
    {
        // EndPoint 指定して
        options.Listen(new IPEndPoint(IPAddress.Loopback, 5000), builder =>
        {
            // ConnectionHandler 登録
            builder.UseConnectionHandler<EchoConnectionHandler>();
        });
    })
    .UseStartup<Startup>();
})
.Build()
.Run();
  • Startupで特別な処置は不要である。
  • Listen時の EndPoint 指定はもちろんできる。Loopback、Any の場合はより簡単なメソッドが用意されている。
  • ConnectionHandler へは ちゃんと DI できる。
  • ConnectionHandler はシングルトン。複数の接続から共有データへアクセスする場合は排他制御する
  • ConnectionContext.TransportPipelines とかいうやつ

あともろもろの留意点はASP.NET Coreパフォーマンスのベスト プラクティス | Microsoft Docsとたぶん同じだろう。

その他

QUIC も実装される(された?)し、やっぱりお任せできると良い。  


関連記事