recv - システムコールの説明 - Linux コマンド集 一覧表
名前
recv, recvfrom, recvmsg - ソケットからメッセージを受け取る
書式
#include <sys/types.h>
#include <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 ()コールは、ソケットからメッセージを受け取るのに使用する。 またソケットのデータ受信にも使うことができ、 このときソケットは接続指向 (connection-oriened) であってもなくてもよい。
from が NULL 以外で、下層のプロトコルから送信元アドレスが分かる場合、 from にはこの送信元アドレスが入れられる。 引き数 fromlen は入出力両用のパラメータで、呼び出し時には from に割り当てたバッファの大きさを入れておき、返ってくる時には実際に from に格納されたアドレスの大きさに変更される。
recv ()コールは通常 接続済みの (connected) ソケット ( connect (2)を参照) についてのみ使用され、 from パラメータに NULL を指定した recvfrom ()と等価である。
これらの三つのルーチンはいずれも、成功した場合にはメッセージの長さを返す。 メッセージが長過ぎて指定されたバッファに入り切らなかった場合には、 メッセージを受信したソケットの種類によっては余分のバイトが捨てられる かもしれない。
ソケットに受け取るメッセージが存在しなかった場合、 受信用のコールはメッセージが到着するまで待つ。 ただし、ソケットが非停止 (nonblocking) に設定されていた場合 ( fcntl (2)を参照) は -1 を返し、外部変数 errno に EAGAIN を設定する。 これらの受信用のコールは、受信したデータのサイズが要求したサイズに 達するまで待つのではなく、何らかのデータを受信すると復帰する (受信されるデータの最大サイズは要求したサイズである)。
select (2) や poll (2) コールを使って、次のデータがいつ届くかを判断できる。
recv ()コールの flags 引き数には、以下の値を 1つ以上、ビット単位の OR (論理和) を取ったものを指定する:
- MSG_DONTWAIT
- 非停止 (non-blocking) 操作を有効にする。 操作が停止するような場合に EAGAIN が返される ( fcntl (2)の F_SETFL で O_NONBLOCK を指定することによっても有効にできる)。
- MSG_ERRQUEUE
-
このフラグを指定すると、
キューに入れられたエラーをソケットのエラーキューから取りだせるようになる。
このエラーは補助メッセージに組み込まれて渡され、
この補助メッセージの種別はプロトコルに依存する
(IPv4 の場合は
IP_RECVERR
)。ユーザは十分なサイズのバッファを用意しなければならない。
補助メッセージに関するより詳細な情報は
cmsg
(3) および
ip
(7) を参照のこと。
エラーの原因となったオリジナルパケットのペイロードは、
msg_iovec
経由で通常のデータとして渡される。
エラーを起こしたデータグラムのオリジナルの宛先アドレスは、
msg_name
経由で参照できる。
ローカルなエラーの場合はアドレスは渡されない (これは cmsghdr の cmsg_len メンバーでチェックできる)。 受信エラーの場合は MSG_ERRQUIE が msghdr にセットされる。 エラーが渡された後には、キューに入っている次のエラーに基いて、 処理待ちのソケット・エラーが再生成され、次のソケット操作の際に渡される。
このエラーは sock_extended_err 構造体で提供される:
#define SO_EE_ORIGIN_NONE 0 #define SO_EE_ORIGIN_LOCAL 1 #define SO_EE_ORIGIN_ICMP 2 #define SO_EE_ORIGIN_ICMP6 3
struct sock_extended_err { u_int32_t ee_errno; /* error number */ u_int8_t ee_origin; /* where the error originated */ u_int8_t ee_type; /* type */ u_int8_t ee_code; /* code */ u_int8_t ee_pad; u_int32_t ee_info; /* additional information */ u_int32_t ee_data; /* other data */ /* More data may follow */ };
struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);
ee_errno にはキューに入れられたエラーのエラー番号が入っている。 ee_origin にはエラーが発生した場所のオリジン・コード (origin code) が入っている。 他のフィールドはプロトコル依存である。 SO_EE_OFFENDER マクロは、この補助的なメッセージを引き数に取って、 エラーの発生したネットワークオブジェクトのアドレスへのポインタを返す。 アドレスが不明の場合には、 sockaddr の sa_family メンバーが AF_UNSPEC になっている。 sockaddr の他のフィールドは不定である。 エラーの発生したパケットのペイロードは通常のデータとして渡される。
ローカルでのエラーの場合にはアドレスは渡されない (これは cmsghdr の cmsg_len メンバーでチェックできる)。 エラーを受け取った場合、 MSG_ERRQUEUE が msghdr に設定される。 エラーが渡された後には、 処理待ちになっていたソケット・エラーが、キューに入っている 次のエラーに基づいて再生成され、次のソケット操作の際に渡される。 - MSG_OOB
- このフラグは、通常のデータ・ストリームでは受信できない 帯域外 (out-of-band) データの受信を要求する。 プロトコルによっては、 通常のデータ・キューの先頭に速達データを置くものがあるが、 そのようなプロトコルではこのフラグは使用できない。
- MSG_PEEK
- このフラグを指定すると、 受信キューの最初のデータを返すとき、キューからデータを削除しない。 したがって、この後でもう一度受信コールを呼び出すと、同じデータが返ることになる。
- MSG_TRUNC
- パケットの長さが渡したバッファよりも長かった場合にも、 パケットの実際の長さを返す。パケット・ソケットに対してのみ有効。
- MSG_WAITALL
-
このフラグは、要求した量いっぱいのデータが到着するまで、
操作を停止 (block) するよう要求する。
但し、シグナルを受信したり、エラーや切断 (disconnect) が発生したり、
次に受信されるデータが異なる型だったりした場合には、
要求した量よりデータが少なくても返ることがある。
recvmsg ()コールは、直接渡すパラメータの数を減らすために msghdr 構造体を使用する。この構造体は <sys/socket.h> で以下のように定義されている:
struct msghdr { void *msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void *msg_control; /* ancillary data, see below */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };
msg_name と msg_namelen は、ソケットが接続されていない場合に送信元のアドレスを指定する。 名前が必要ない場合には msg_name に NULL ポインタを指定する。 msg_iov と msg_iovlen フィールドは readv (2) に記述されているような分解/結合用のベクトル (scatter-gather locations) を指定する。 msg_control フィールドは msg_controllen の長さを持ち、他のプロトコル制御メッセージや 種々の補助データのためのバッファへのポインタである。 recvmsg ()を呼ぶ際には、 msg_controllen に msg_control のバッファの長さを入れておく必要がある。 コールが成功して返った場合、制御メッセージ列の長さが入っている。
メッセージの形式は以下の通り:
struct cmsghdr { socklen_t cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by u_char cmsg_data[]; */ };
補助データは、 cmsg (3) に定義されたマクロ経由でのみアクセスすべきである。
例をあげると、 Linux はこの補助データのメカニズムを、 Unix ソケット上での拡張エラーや IP オプション、 ファイル・ディスクリプタの受け渡しに利用している。
msghdr の msg_flags フィールドは recvmsg ()からのリターン時に設定される。ここにはいくつかのフラグが入る。
- MSG_EOR
- これはレコードの終り (end-of-record) を示し、 返されたデータが完全なレコードであることを示す (一般的には SOCK_SEQPACKET 型のソケットで使用される)。
- MSG_TRUNC
- データグラムが与えられたバッファより大きかったために、 データグラムのはみ出した部分が捨てられたことを示す。
- MSG_CTRUNC
- 補助データのためのバッファが不足したために、 制御データの一部が捨てられたことを示す。
- MSG_OOB
- 速達データや帯域外データを受信したことを示す。
- MSG_ERRQUEUE
- データは受信しなかったが ソケットのエラー・キューから拡張エラーを受信したことを示す。
返り値
これらのコールは受信したバイト数を返す。 エラーの場合は -1 を返す。 接続先が正しくシャットダウンを実行した場合は、返り値は 0 となる。
エラー
これらはソケット層で発生する一般的なエラーである。 他のエラーが下層のプロトコル・モジュールで生成され、 返されるかもしれない。 それらのマニュアルを参照すること。
- EAGAIN
- ソケットが非停止 (non-blocking) に設定されていて 受信操作が停止するような状況になったか、 受信に時間切れ (timeout) が設定されていて データを受信する前に時間切れになった。
- EBADF
- 引き数 s が不正なディスクリプタである。
- ECONNREFUSED
- リモートのホストでネットワーク接続が拒否された (よくある理由としては、要求したサービスが起動されていないなどがある)。
- EFAULT
- 受信バッファへのポインタがプロセスのアドレス空間外を指している。
- EINTR
- データを受信する前に、シグナルが配送されて割り込まれた。
- EINVAL
- 不正な引き数が渡された。
- ENOMEM
- recvmsg ()のためのメモリが確保できなかった。
- ENOTCONN
- ソケットに接続指向プロトコルが割り当てられており、 まだ接続されていない ( connect (2)と accept (2) を参照のこと)。
- ENOTSOCK
- 引き数 s がソケットを参照していない。
準拠
4.4BSD (これらの関数は 4.2BSD で現われた), POSIX.1-2001。
POSIX.1-2001 では、 MSG_OOB , MSG_PEEK , MSG_WAITALL フラグだけが記載されている。
注意
上記のプロトタイプは glibc2 にしたがっている。
Single Unix Specification でも同様だが、
返り値の型が ssize_t となっている
(一方で 4.x BSD や libc4 や libc5 は全て `int' を使用している)。
flags
引き数は 4.x BSD では `int' だが、libc4 と libc5 では `unsigned int' である。
len
引き数は 4.x BSD では `int' だが、 libc4 と libc5 では `size_t' である。
fromlen
引き数は 4.x BSD, libc4, libc5 では `int *' である。
現在の `socklen_t *' は POSIX で発案された。
accept
(2) も参照すること。
POSIX.1-2001 では、構造体
msghdr
のフィールド
msg_controllen
は
socklen_t
型であるべきだとされているが、
現在の glibc (glibc 2.4) では
size_t
型である。
関連項目
fcntl
(2),
getsockopt
(2),
read
(2),
select
(2),
shutdown
(2),
socket
(2),
cmsg
(3),
sockatmark
(3)