$OpenXM: OpenXM/src/ox_socket/DOCUMENT.ja,v 1.6 2000/12/01 07:53:03 maekawa Exp $ Drafts of the specification of the OpenXM standard socket APIs. 1. ox_connect connect(2) の代わりに ox_connet を使うべし. int ox_connect(const char *hostname, int port, struct ox_sockopt *opt); hostname - 接続先のホスト名 port - 接続先のポート番号 opt - setsockopt(2) へ渡したいオプション群 setsockopt(2) の第一引数はソケット番号であるが, これは ox_connect 内で作成される. struct ox_sockopt { ... int level; /* setsockopt(2) の第二引数 */ int option_name; /* setsockopt(2) の第三引数 */ void *option_value; /* setsockopt(2) の第四引数 */ socklen_t option_len; /* setsockopt(2) の第五引数 */ ... }; setsockopt(2) に渡すべき内容がない場合は, ox_connect に NULL を渡せばよい. 成功すればソケット番号を, 失敗すれば -1 を返す. 2. ox_listen listen(2) の代わりに ox_listen を使うべし. struct ox_sockarray * ox_listen(const char *hostname, int *port, int backlog, struct ox_sockopt *opt); hostname - 接続先のホスト名 port - 接続先のポート番号 backlog - listen(2) の第二引数 opt - setsockopt(2) へ渡したいオプション群 (ox_connect と同様) #define OX_MAXSOCKS 32 struct ox_sockarray { int sock[OX_MAXSOCKS]; int nsocks; }; hostname が NULL の場合, ox_listen は任意のホスト (IPv4 においては 0.0.0.0, IPv6 においては ::) からの接続を待ち受ける. 成功すれば listen(2) しているソケットの数と配列への構造体への ポインタを, 失敗すれば NULL を返す. ox_sockarray 構造体を使う理由: 待ち受けているソケットは必ずしもひとつではない. IPv4 と IPv6 双方が利用可能な (デュアルスタックな) マシンにおいて, IPv4 および IPv6 をサポートしている sshd (OpenSSH など) が任意のホストからの接続を 待ち受けている場合は, 以下のようになっている. # sockstat | grep sshd root sshd 177 4 tcp4 *:22 *:* root sshd 177 3 tcp46 *:22 *:* 3. ox_accept accept(2) の代わりに ox_accept を使うべし. int ox_accept(struct ox_sockarray *socks); socks - ox_listen の戻り値 成功すれば accept(2) されたソケット番号を, 失敗すれば -1 を返す. 4. ox_getsockname getsockname(2) の代わりに ox_getsockname を使うべし. int ox_getsockname(int socket, struct sockaddr **addr, socklen_t *addrlen); socket - 有効なソケット番号 addr - sockaddr 構造体へのポインタのポインタ addrlen - sockaddr 構造体の長さ 成功すれば 0 を, 失敗すれば -1 を返す. 取得された sockaddr 構造体は addr に格納され, 長さは addrlen に格納される. getsockname(2) を使わない理由: sockaddr 構造体は, 今日では汎用的なインターフェイスを 提供しているにしかすぎない. 実際のサイズはそれぞれの アドレスファミリごとに違うので, 現在では, 実質的な sockaddr 構造体の placeholder として, sockaddr_storage 構造体が定義されている. ただし, この構造体は, 事実上 IPv6 登場以降の OS にしか実装されておらず, OpenXM として 実装を仮定するのはよくない. そこで, ox_getsockname という wrapper を用意し, 実際の挙動を隠蔽することにした. 中身が必要となる場合として, ポート番号の取得があるが, これについては, ox_getport という wrapper を用意し, sockaddr 構造体をさらに隠蔽できるようにしてある. ox_getsockname で取得した sockaddr 構造体へ割り当てたメモリは, 必要がなくなった時点で確実に free(2) されるべきである. GC を用いている場合は, この限りではない. しかし, sockaddr 構造体を 永続的に使用しなければならない状況はまず考えられず, GC を用いて 管理する必要は一切ないと思われる. 5. ox_getport int ox_getport(int socket); socket - 有効なソケット番号 ポート番号の取得に関する汎用的なインターフェイスは存在しない. それぞれのアドレスファミリごとに個別に対処する必要がある. この操作を OpenXM として用意したのが, ox_getport である. 成功すればポート番号を, 失敗すれば -1 を返す. 注意事項: 一部の OS には socklen_t が宣言されていない. Single UNIX Specification, version 2 あるいは, POSIX に基づいて 32 ビット符号無し整数と仮定してよいだろう. これ以上の大きさが必要となるときと, 我々の死とどちらが早いだろうか... OpenXM 標準ソケット API は, 現時点で IPv4 もしくは IPv6 での 利用しか想定していない. この制限は, この API 群の拡張性に問題が あるのではなく, これら以外のアドレスファミリにおいては, いくつかの関数の動作を保証できないからである. 将来, 上記以外の アドレスファミリのサポートが必要になった場合は, そのアドレスファミリ において, どのような動作をすべきを十分に考慮した上で, すみやかに拡張される.