Re はやいTCPサーバの書き方

はやいTCPサーバの書き方 - nyaxtのPC作業ログ について、いくつか気になった点があったので。

Nagleアルゴリズムは、相手側のACK送信をまとめてくれるものです。これは、下記の様にアプリケーション側でパケットを意識した処理を行っている場合、邪魔になることがあります。

違うと思います。自分の理解では、Nagle アルゴリズムは、ACK を受信していないデータがある場合に、次のパケットを送信しない、というものです。RFC896 から引用すると、

The solution is to inhibit the sending of new TCP segments when new outgoing data arrives from the user if any previously transmitted data on the connection remains unacknowledged.

http://www.ietf.org/rfc/rfc896.txt

です。

次に Nagle アルゴリズムTCP_NODELAY オプションの関係についてですが、TCP_NODELAY は、アプリケーションプログラマの視点からは、パケットの遅延処理を行わない、という意味になると思います。TCP プロトコルの実装者の視点からは、Nagle アルゴリズムだけでなく、delayed acknowledgement も行わない*1、といった形になります。

一方で、b:id:Kanatoko さんが指摘されているように、複数の write(2) や ACK を単一パケットにまとめるかどうか、は、プロトコル実装が自由に決めて問題のない (はず) のことです *2。アプリケーションからはパケットがどう分割されていようが、TCP は単なるストリームであり、

前のリクエストのbodyと次のリクエストのheaderがまとめられてしまったりして、いびつなパケットになってしまう

という現象によってアプリケーションの動作が変化するのであれば、それはアプリケーションのバグです。

現実問題としてクライアント (あるいはサーバ) の実装が壊れていることはあるのですが、その場合はパケットの分割を調整してもワークアラウンドにはなりません *3。そのような場合は、パイプライン処理を行わない、という解決策を採ることになります (参考: Kazuho@Cybozu Labs: サーバシグニチャは隠さないのが当たり前)

*1:18:57 追記: これは間違いです。すみません。see man tcp

*2:というか、パフォーマンスを稼ぎたいのであれば、システムコール回数を減らすべきだし、その上でまだパケットが OS によってまとめられるのであれば、それはむしろパフォーマンス向上につながるので喜ばしいことだと思う

*3:アプリケーションが別々のパケットを別々のシステムコールで受信することになるとは限らないため