socket(2) の man ページなどを見ると分かりますが、SOCK_STREAM, SOCK_DGRAM, SOCK_RAW などと同じ並びに SOCK_SEQPACKET というのがあります。

IP ネットワークでは普通サポートされないので使ったことのない人も多いと思います。実際私も15年ぐらいソケットプログラミングやってますが、使ったことはありませんでした。ちょいと必要になってしまったので備忘録も兼ねてまとめておきます。

仕様

まず仕様から。赤地は SOCK_STREAM と同じ性質で、青地は SOCK_DGRAM と同じ性質です。

SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET
種別 コネクション指向 コネクションレス コネクション指向
順序性 ×
信頼性 ×
転送単位 バイトストリーム データグラム データグラム

表を見ると分かる通り、ほぼ SOCK_STREAM と同じです。「SOCK_STREAM のデータグラム版」と考えておくのがいいでしょう。

AF_LOCAL (AF_UNIX) での実装

仕様は上のとおりなのですが、実装となるといろいろと細かい話が出てきます。(なお、ここでは AF_LOCAL の話だけします)

  • 多くの POSIX 実装において、(AF_LOCAL では)SOCK_DGRAM は順序性も信頼性も持つ。というか、そうでない実装は見たことがない。つまり、上の表における SOCK_SEQPACKET と SOCK_DGRAM との差異はコネクション指向かどうかという点だけになる。
  • SOCK_SEQPACKET は実装されていない環境があり、古めの OS だと使えないことがある。NetBSD なんかは現時点の stable である 5.0 ですら使えず、6.0-beta でようやく追加された。また、ググってみると Mac OS X だと socketpair() で SOCK_SEQPACKET が使えないような記述が見つかる。
  • BSD の場合、ソケットバッファが埋まった場合の挙動が SOCK_DGRAM と SOCK_SEQPACKET で違う。SOCK_DGRAM だと select() 等では writable と報告され実際に write すると ENOBUFS でエラーになるが、SOCK_SEQPACKET だと writable でなくなり実際に write するとブロックする。Linux だとどちらでも writable でなくなり実際に write するとブロックする。

SOCK_SEQPACKET はデータグラム型という点で SOCK_DGRAM と似ていますが、それ以外の性質については SOCK_STREAM と同じです。上のとおり SOCK_DGRAM でもほとんどの実装では信頼性がありますが、それは書き込みに成功したものが読み込まれることが保証される(カーネル内で行方不明になったりしない)というだけです。捨ててはいけないデータを書き込めなかったときに再試行しようとすると、移植性のあるイベントドリブンアプリケーションの場合はめんどくさいコードを書くことになります。SOCK_SEQPACKET なら単に select() 等で待機すればいいだけです。ノンブロッキングである必要がないなら、そもそも何もする必要がありません。

というわけで、みなさん SOCK_SEQPACKET はもっと使っていいと思うのですよ。

Trackback

no comment untill now

Add your comment now