socket(2), bind(2), listen(2), accept(2)

本日は、MIT Open CoursewareのLecture14で、socket(2), bind(2), listen(2), accept(2)など。

アレコレ参考にしながら、最もシンプルなサーバとクライアントを書いてみた。

サーバ

クライアント

socket(2)

#include <sys/socket.h>
int socket(int domain, int type, int protocol);  

通信のためのエンドポイントを作成し、ディスクリプター(descriptor)を返す。 typeはAF_INETならIPv4 インターネット・プロトコルで、AF_UNIXはローカル通信(UNIXドメインソケット)を指す。

socketの戻り値はfile descriptorになるが、確認してみるとsocketになってるのがわかる。

[vagrant@localhost ~]$ ls -la /proc/2099/fd
合計 0
dr-x------ 2 vagrant vagrant  0  1月 31 13:36 2014 .
dr-xr-xr-x 7 vagrant vagrant  0  1月 31 13:36 2014 ..
lrwx------ 1 vagrant vagrant 64  1月 31 13:36 2014 0 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  1月 31 13:36 2014 1 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  1月 31 13:36 2014 2 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  1月 31 13:36 2014 3 -> socket:[18402]

bind(2)

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

socket(2) でソケットが作成されたとき、そのソケットは名前空間 (アドレス・ファミリー) に 存在するが、アドレスは割り当てられていない。 bind() は、ファイルディスクリプタ sockfd で参照されるソケットに addr で指定されたアドレスを割り当てる。 addrlen には addr が指すアドレス構造体のサイズをバイト単位で指定する。 伝統的にこの操作は 「ソケットに名前をつける」 と呼ばれる。

listen(2)

#include <sys/socket.h>
int listen(int sockfd, int backlog);

listen() は sockfd が参照するソケットを接続待ちソケット (passive socket) として印をつける。 接続待ちソケットとは、 accept(2) を使って到着した接続要求を受け付けるのに使用されるソケットである。

accept(2)

#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

接続待ちソケット socket 宛ての保留状態の接続要求が入っているキューから 先頭の接続要求を取り出し、接続済みソケットを新規に生成し、 そのソケットを参照する新しいファイル・ディスクリプタを返す。 新規に生成されたソケットは、接続待ち (listen) 状態ではない。

[vagrant@localhost tmp]$ ls -la /proc/2143/fd
合計 0
dr-x------ 2 vagrant vagrant  0  2月  2 06:59 2014 .
dr-xr-xr-x 7 vagrant vagrant  0  2月  2 06:59 2014 ..
lrwx------ 1 vagrant vagrant 64  2月  2 06:59 2014 0 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  2月  2 06:59 2014 1 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  2月  2 06:59 2014 2 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64  2月  2 06:59 2014 3 -> socket:[20965]
lrwx------ 1 vagrant vagrant 64  2月  2 07:02 2014 4 -> socket:[20966]

新しいファイルディスクリプタがつくられてるのが確認できる。

echoサーバ

ちょっとだけ、押し進めてechoサーバを書いてみる。

echo_server

echo_client