EN JA
RECV(2)
RECV(2) FreeBSD System Calls Manual RECV(2)

名称

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

ライブラリ

Standard C Library (libc, -lc)

書式

#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 * restrict from, socklen_t * restrict fromlen);

ssize_t
recvmsg( int s, struct msghdr *msg, int flags);

解説

recvfrom() と recvmsg() システムコールは、ソケットからメッセージを受信するために使用され、接続指向であるかどうかにかかわらず、ソケットでデータを受信するために使用されます。

from が NULL ポインタでなく、ソケットが接続指向でないなら、メッセージのソースアドレスが、書き込まれます。 fromlen 引数は、値と結果の引数であり、 from に対応するバッファのサイズに初期化され、戻り時には、保存されたアドレスの実際のサイズを示すように変更されます。

recv() システムコールは、通常 接続された ソケット上だけで使用され ( connect(2) を参照)、 from 引数に NULL ポインタを指定した recvfrom() と同一です。

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

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

次のデータがいつ到着するかを判定するには、 select(2) システムコールを使うことができます。

recv() 関数への flags 引数は、次の値の 1 つまたは複数の論理和 ( or) から成ります:

MSG_OOB プロセス帯域外データ
MSG_PEEK 着信メッセージの覗き見 (peek)
MSG_WAITALL 要求の完全な実行、またはエラーを待つ
MSG_DONTWAIT ブロックしない
MSG_CMSG_CLOEXEC 受信された fds close-on-exec を設定します

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

recvmsg() システムコールは、直接に指定される引数の数を最小にするために msghdr 構造体を使用します。この構造体は、 < sys/socket.h> で定義されているように、次の形式になっています:

struct msghdr { 
 void  *msg_name; /* オプションのアドレス */ 
 socklen_t  msg_namelen; /* アドレスのサイズ */ 
 struct iovec *msg_iov; /* スキャッタ/ギャザ配列 */ 
 int   msg_iovlen; /* msg_iov の要素数 */ 
 void  *msg_control; /* 補助データ, 下記参照 */ 
 socklen_t  msg_controllen;/* 補助データのバッファ長 */ 
 int   msg_flags; /* 受信されたメッセージのフラグ */ 
};

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

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

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

オープンファイル記述子は、これで AF_UNIX ドメインソケット用の補助データとして引き渡され、その際、 cmsg_levelSOL_SOCKET に設定され、 cmsg_typeSCM_RIGHTS に設定されます。受信された記述子の close-on-exec フラグは、 recvmsg() に渡される MSG_CMSG_CLOEXEC フラグにしたがって設定されます。

SCM_CREDScmsg_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]; /* グループ */ 
};

送信者が sendmsg() システムコールへの SCM_CREDS 制御メッセージタイプとしてタグ付けされた、上記の struct のための十分な空間がある補助データを供給するなら、カーネルは、送信するプロセスの資格証明情報に書き込んで、受信者にそれを配信します。通常、受信者が送信者の制御をしていないので、資格証明情報を検索するこの方法は、信頼できません。リモート側の資格証明の信頼できる検索については、受信ソケットで LOCAL_CREDS ソケットオプションを使用するように勧められます。詳細については、 unix(4) を参照してください。

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

戻り値

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

エラー

呼び出しは、次の場合に失敗します:
[ EBADF]
引数 s が有効な記述子ではありません。
[ ECONNRESET]
リモート側のソケット端が強制的にクローズされました。
[ ENOTCONN]
ソケットは、接続指向プロトコルと結び付けられていますが、接続されていません ( connect(2)accept(2) を参照)。
[ ENOTSOCK]
引数 s は、ソケットを参照していません。
[ EMSGSIZE]
接続中にオープンされている権利 (ファイル記述子) を recvmsg() システムコールを使用して受信しようとしました。しかし、受信側プログラムのにそれらを受け取るだけの十分な空きファイル記述子スロットがありませんでした。この場合、該当する記述子は、クローズされ、保留されているデータは、別の recvmsg() 呼び出しで戻せます。
[ EAGAIN]
ソケットが非ブロッキングとマークされているとき、受信操作でブロックしました。あるいは、受信タイムアウトが設定されていて、データが受信される前にタイムアウトになりました。
[ EINTR]
データが受信可能になる前に、受信がシグナルによって割込まれました。
[ EFAULT]
受信バッファポインタが、プロセスに割り当てられたアドレス空間の範囲外を指しています。

歴史

recv() 関数は、 4.2BSD で登場しました。
March 19, 2013 FreeBSD