RECV(2)

名称
recv, recvfrom, recvmsg - ソケットからメッセージを受信する

ライブラリ
libc

書式
<sys/types.h> <sys/socket.h> ssize_t recv(int s, void *buf, size_t len, int flags) ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) ssize_t recvmsg(int s, struct msghdr *msg, int flags)

解説
recvfrom() と recvmsg() は、ソケットからのメッセージを受信するのに使用されます。 ソケットが接続指向であるかどうかにかかわらず、ソケット上のデータを 受信するのに使用できます。

from が nil でなく、ソケットが接続指向でない場合、 ここにはメッセージのソースアドレスが保存されます。 fromlen は「値 - 結果」パラメータであり、 from に対応するバッファのサイズに初期化され、 戻り時には保存されたアドレスの実際のサイズを示すように 変更されます。

recv() 呼び出しは、通常 接続された ソケット上だけで使用され (connect(2) を参照)、 from パラメータに nil を指定した recvfrom() と同一です。これは冗長なので、将来のリリースでは サポートされない可能性があります。

これら 3 つのルーチンは正常に完了するとメッセージの長さを返します。 メッセージが長すぎて指定のバッファに収まらない場合、 メッセージを受信したソケットのタイプによっては 超過分のバイトが破棄されることがあります (socket(2) を参照)。

ソケットにメッセージが無い場合は、ソケットが非ブロッキング (fcntl(2) を参照) の場合を除き、呼び出しはメッセージが到着するのを待ちます。 ソケットが非ブロッキングの場合、値 -1 が返され、外部変数 errno が EAGAIN に設定されます。通常、受信呼び出しは要求された量を受信するまで待たずに、 要求された量を上限として得られたデータを返します。この動作は、 getsockopt(2) で解説されているソケットレベルのオプション SO_RCVLOWAT および SO_RCVTIMEO によって影響を受けます。

次のデータがいつ到着するかを判定するには select(2) 呼び出しを使うことができます。

recv 呼び出しへの flags 引数は、次の値の 1 つまたは複数の論理和 (or) から成ります。
MSG_OOB | プロセス帯域外データ
MSG_PEEK | 着信メッセージの覗き見 (peek)
MSG_WAITALL | 要求の完全な実行、またはエラーを待つ

MSG_OOB フラグは帯域外データの受信を要求し、 通常のデータストリームからは受信しません。 急送データを通常のデータ待ち行列の先頭に配置するプロトコルもありますが、 このフラグはそのようなプロトコルでは使用できません。MSG_PEEK フラグは 受信待ち行列の先頭からデータを除去することなく、そのデータを 返します。したがって、後続の受信呼び出しは同じデータ を返します。MSG_WAITALL フラグは要求が完全に満たされるまで ブロックするように要求します。 しかし、シグナルが捕捉された場合、エラーまたは切断が発生した場合、 または受信する次のデータが返されたタイプと異なる 場合、呼び出しは要求されたより少ないデータを返す可能性があります。

recvmsg() 呼び出しは、直接に指定されるパラメータの数を最小にするために msghdr 構造体を使用します。この構造体は <sys/socket.h> で定義されているように、次の形式になっています。

    struct msghdr {
    	caddr_t	msg_name;	/* アドレス(オプション) */
    	u_int	msg_namelen;	/* アドレスのサイズ */
    	struct	iovec *msg_iov;	/* スキャッタ/ギャザー配列 */
    	u_int	msg_iovlen;	/* msg_iov の要素数 */
    	caddr_t	msg_control;	/* 補助データ、後述 */
    	u_int	msg_controllen; /* 補助データのバッファ長 */
    	int	msg_flags;	/* 受信されたメッセージ上のフラグ */
    };

ここで msg_name と msg_namelen は、ソケットが接続されていない場合に、宛先アドレスを指定します。 名前を要求しない場合や必要でない場合、 msg_name は NULL ポインタとして指定できます。 msg_iov と msg_iovlen は read(2) で説明されているようにスキャッタ/ギャザーの場所を記述します。 msg_control は、長さが msg_controllen の、他のプロトコル制御に関連するメッセージまたはその他の 各種補助データ用のバッファを指しています。メッセージは次の形式です。

    struct cmsghdr {
    	u_int	cmsg_len;	/* データバイトカウント、hdr を含む */
    	int	cmsg_level;	/* メッセージを生成したプロトコル */
    	int	cmsg_type;	/* プロトコルに固有のタイプ */
    /*	u_char	cmsg_data[]; が後に続く */
    };

たとえば、これを使用して XNS/SPP において データストリームの変化を知ることができます。また、ISO において accept() 呼び出しの直後に、データバッファを伴わずに recvmsg を要求して、 ユーザ接続要求データを得ることができるでしょう。

オープンされたファイル記述子はこれで AF_UNIX ドメインソケット用の補助データとして引き渡され、その際、 cmsg_level が SOL_SOCKET に設定され、 cmsg_type が SCM_RIGHTS に設定されます。

SCM_CREDS の cmsg_type を使用して、プロセスの認証情報を AF_UNIX ドメインソケット用の補助データとして 渡すこともできます。このケースでは、 cmsg_data は、構造体 cmsgcred である必要があります。これは 次のように <sys/socket.h> 内で定義されています。

    struct cmsgcred {
    	pid_t	cmcred_pid;		/* 送信プロセスの PID */
    	uid_t	cmcred_uid;		/* 送信プロセスの実 UID */
    	uid_t	cmcred_euid;		/* 送信プロセスの実効 UID */
    	gid_t	cmcred_gid;		/* 送信プロセスの実 GID */
    	short	cmcred_ngroups;		/* グループの数 */
    	gid_t	cmcred_groups[CMGROUP_MAX];	/* グループ */
    };

カーネルは送信プロセスの認証情報を記入し、それを受信側へ配信します。

msg_flags フィールドは受信済みメッセージに従って戻り時に設定されます。 MSG_EOR は end-of-record、つまり返されたデータでレコードが 完結していることを示します (一般には、タイプ SOCK_SEQPACKET のソケットとともに使用されます)。 MSG_TRUNC は、提供されたバッファよりデータグラムが大きかったので、 データグラムの後ろの部分が切り捨てられたことを示します。 MSG_CTRUNC は、補助データ用のバッファ内の空間の不足のためにいくらかの制御データが 切り捨てられたことを示します。 MSG_OOB は、急送または帯域外データが受信されたことを示します。

戻り値
これらの呼び出しは受信したバイト数を返し、エラーが起きた場合は -1 を返します。

エラー
呼び出しは次の場合に失敗します。

[EBADF]
    引数 s が有効な記述子ではありません。

[ENOTCONN]
    ソケットは接続指向プロトコルと結び付けられていますが、接続されていません (connect(2) と accept(2) を参照)。

[ENOTSOCK]
    引数 s はソケットを参照していません。

[EAGAIN]
    ソケットが非ブロッキングとマークされているとき、 受信操作でブロックしました。 あるいは、受信タイムアウトが設定されていて、 データが受信される前にタイムアウトになりました。

[EINTR]
    データが受信可能になる前に、受信がシグナルによって割込まれました。

[EFAULT]
    受信バッファポインタが、プロセスに割り当てられたアドレス空間の 範囲外を指しています。

関連項目
fcntl(2), getsockopt(2), read(2), select(2), socket(2)

歴史
recv() 関数は 4.2BSD で登場しました。