recv

Autres langues

Langue: ja

Version: 2002-12-31 (mandriva - 01/05/08)

Section: 2 (Appels système)

名前

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 を返し、外部変数 errnoEAGAIN を設定する。 これらの受信用のコールは、受信したデータのサイズが要求したサイズに 達するまで待つのではなく、何らかのデータを受信すると復帰する (受信されるデータの最大サイズは要求したサイズである)。

select(2) や poll(2) コールを使って、次のデータがいつ届くかを判断できる。

recv() コールの flags 引き数には、以下の値を 1つ以上、ビット単位の OR (論理和) を取ったものを指定する:

MSG_DONTWAIT
非停止 (non-blocking) 操作を有効にする。 操作が停止するような場合に EAGAIN が返される (fcntl(2) の F_SETFLO_NONBLOCK を指定することによっても有効にできる)。
MSG_ERRQUEUE
このフラグを指定すると、 キューに入れられたエラーをソケットのエラーキューから取りだせるようになる。 このエラーは補助メッセージに組み込まれて渡され、 この補助メッセージの種別はプロトコルに依存する (IPv4 の場合は IP_RECVERR)。 ユーザは十分なサイズのバッファを用意しなければならない。 補助メッセージに関するより詳細な情報は cmsg(3) および ip(7) を参照のこと。 エラーの原因となったオリジナルパケットのペイロードは、 msg_iovec 経由で通常のデータとして渡される。 エラーを起こしたデータグラムのオリジナルの宛先アドレスは、 msg_name 経由で参照できる。
ローカルなエラーの場合はアドレスは渡されない (これは cmsghdrcmsg_len メンバーでチェックできる)。 受信エラーの場合は MSG_ERRQUIEmsghdr にセットされる。 エラーが渡された後には、キューに入っている次のエラーに基いて、 処理待ちのソケット・エラーが再生成され、次のソケット操作の際に渡される。
このエラーは 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 マクロは、この補助的なメッセージを引き数に取って、 エラーの発生したネットワークオブジェクトのアドレスへのポインタを返す。 アドレスが不明の場合には、 sockaddrsa_family メンバーが AF_UNSPEC になっている。 sockaddr の他のフィールドは不定である。 エラーの発生したパケットのペイロードは通常のデータとして渡される。
ローカルでのエラーの場合にはアドレスは渡されない (これは cmsghdrcmsg_len メンバーでチェックできる)。 エラーを受け取った場合、 MSG_ERRQUEUEmsghdr に設定される。 エラーが渡された後には、 処理待ちになっていたソケット・エラーが、キューに入っている 次のエラーに基づいて再生成され、次のソケット操作の際に渡される。
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_namemsg_namelen は、ソケットが接続されていない場合に送信元のアドレスを指定する。 名前が必要ない場合には msg_name に NULL ポインタを指定する。 msg_iovmsg_iovlen フィールドは readv(2) に記述されているような分解/結合用のベクトル (scatter-gather locations) を指定する。 msg_control フィールドは msg_controllen の長さを持ち、他のプロトコル制御メッセージや 種々の補助データのためのバッファへのポインタである。 recvmsg() を呼ぶ際には、 msg_controllenmsg_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_controllensocklen_t 型であるべきだとされているが、 現在の glibc (glibc 2.4) では size_t 型である。

recvfrom() の利用例が getaddrinfo(3) に記載されている。

関連項目

fcntl(2), getsockopt(2), read(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3)