ASP.NET CoreのドキュメントにKestrel(Webサーバー)ドキュメントにマネージドソケットに基づくと書いてあり、
どうしているのか気になったので簡単に確認してみた。(そして、わりと速いらしい)
コードはGithub。
ASP.NET Core の作法として、Kestrel ServerのStartAsync
が多分呼ばれる。
各種BindAsync
をConfigureAwait(false)
として経由して、SocketTransportへ到達する。
SocketTransportにて、リッスン用のソケット(Socket
)生成、Bind
、Listen
を行い、そのリッスンソケットを使ってTask.Run()
内でAcceptループを回している。
Acceptは await AcceptAsync()
で待ち、接続あったら両方向のPipelines.Pipe
を生成して、送受信処理をそれぞれawaitで待つ。完了したらDispose
。
ソケット送受信処理ではTask(ValueTask)を返す拡張メソッドを使用せずSocketAsyncEventArgs
という(たぶん古い非同期プログラミングモデル用)のを拡張して使っている。こっちのほうが速いのか?
後、データ受け渡しがMemory<>
とかReadOnlySequence<>
になってるね。
ということで、とりあえず
Socket直接触る(TCPxxx, UDPxxxでやらない)、AcceptAsync/SendAsync/ReceiveAsync(/ConnectAsyncも) をawaitする、データのやり取りはPipelinesとかMemoryで
をしておけばよいのかな。
追記
2019-02-27
Socketの非同期実装についてdotnet/corefx | GitHubの中を覗いてみたら、Unix(Linux/macOS)のときは下(ネイティブ実装)のほうでepoll/kqueue使ってイベント監視していた。
だからawaitしておけば、いい感じにI/Oイベント拾ってスレッドが割り当てられて、それなりに動く。ということでいいのか。
フレームワークも色々あるようなので、直接触らないず済ませるくらいで丁度よいかもしれない。