RECV(2) | Linux Programmer's Manual | RECV(2) |
recv, recvfrom, recvmsg - ソケットからメッセージを受け取る
#include <sys/types.h>
#include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
recv(), recvfrom(), recvmsg() コールは、 ソケットからメッセージを受け取るのに使用される。 これらはコネクションレス型のソケットにも接続指向 (connection-oriened) 型のソケットにも使用できる。 このページでは、まずこれら 3 つのシステムコールすべてに共通の機能について説明し、 システムコール間の違いについて説明する。
これらの三つのシステムコールはいずれも、成功した場合にはメッセージの長さを返す。 メッセージが長過ぎて指定されたバッファーに入り切らなかった場合には、 メッセージを受信したソケットの種類によっては余分のバイトが捨てられる かもしれない。
ソケットに受け取るメッセージが存在しなかった場合、 受信用のコールはメッセージが到着するまで待つ。 ただし、ソケットが非停止 (nonblocking) に設定されていた場合 (fcntl(2) を参照) は -1 を返し、外部変数 errno に EAGAIN か EWOULDBLOCK を設定する。 これらの受信用のコールは、受信したデータのサイズが要求したサイズに 達するまで待つのではなく、何らかのデータを受信すると復帰する (受信されるデータの最大サイズは要求したサイズである)。
アプリケーションは select(2), poll(2), epoll(7) を使って、ソケットにさらにデータが到着しているかを判定することができる。
flags 引き数には、以下の値を 1つ以上、ビット単位の論理和 を取ったものを指定する:
このエラーは
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 {
uint32_t ee_errno; /* error number */
uint8_t ee_origin; /* where the error originated */
uint8_t ee_type; /* type */
uint8_t ee_code; /* code */
uint8_t ee_pad; /* padding */
uint32_t ee_info; /* additional information */
uint32_t ee_data; /* other data */
/* More data may follow */ }; struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);
Internet ストリームソケットでの利用については tcp(7) を参照。
recvfrom() は受信したメッセージをバッファー buf に格納する。 呼び出し元はバッファーサイズを len で指定しなければならない。
src_addr が NULL 以外で、下層のプロトコルからメッセージの送信元アドレスが分かる場合、 この送信元アドレスが src_addr が指すバッファーに格納される。 この場合、 addrlen は入出力両用の引き数となる。 呼び出し前に、呼び出し元は src_addr に割り当てたバッファーの大きさで初期化しておくべきである。 返ってくる時には、 addrlen は送信元アドレスの実際の大きさに変更される。渡されたバッファーが小さ過ぎる場合には、返されるアドレスの末尾は 切り詰められる。この場合には、 addrlen では、呼び出し時に渡された値よりも大きな値が返される。
呼び出し元が送信元アドレスを必要としない場合は、 src_addr と addrlen には NULL を指定すべきである。
recv() コールは通常 接続済みの (connected) ソケットに対してのみ使用される (connect(2) 参照)。次の呼び出しと等価である。
recvfrom(fd, buf, len, flags, NULL, 0));
recvmsg()
コールは、直接渡す引き数の数を減らすために
msghdr
構造体を使用する。この構造体は
<sys/socket.h>
で以下のように定義されている:
struct iovec { /* Scatter/gather array items */
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */ }; struct msghdr {
void *msg_name; /* 追加のアドレス */
socklen_t msg_namelen; /* アドレスのサイズ */
struct iovec *msg_iov; /* scatter/gather 配列 */
size_t msg_iovlen; /* msg_iov の要素数 */
void *msg_control; /* 補助データ (後述) */
size_t msg_controllen; /* 補助データバッファー長 */
int msg_flags; /* 受信メッセージのフラグ */ };
フィールド msg_name は、 ソケットが接続されていない場合に送信元アドレスを返すのに使用されるバッファーを指す。 このバッファーは呼び出し元が確保する。 呼び出し元は呼び出し前に msg_namelen にこのバッファーの大きさを設定しなければならない。 呼び出しが成功した場合、呼び出しから返って来た際には msg_namelen には返されるアドレスの長さが入っている。 アプリケーションが送信元アドレスを知る必要がない場合には、 msg_name に NULL を指定することができる。
msg_iov と msg_iovlen フィールドは scatter-gather 用の場所を指定する。 readv(2) に説明がある。
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
unsigned char cmsg_data[]; */ };
補助データは、 cmsg(3) に定義されたマクロ経由でのみアクセスすべきである。
例をあげると、 Linux はこの補助データのメカニズムを、 UNIX ドメインソケット上での拡張エラーや IP オプション、 ファイルディスクリプターの受け渡しに利用している。
msghdr の msg_flags フィールドは recvmsg() からのリターン時に設定される。ここにはいくつかのフラグが入る。
これらのコールは受信したバイト数を返す。 エラーの場合は -1 を返し、 errno にエラーを示す値を設定する。
ストリームソケットの接続相手が正しくシャットダウンを実行した場合は、 返り値は 0 (昔ながらの "end-of-file" の戻り値) となる。
いくつかのドメインのデータグラムソケット (UNIX ドメインやインターネットドメインなど) では、長さ 0 のデータグラムが送信できる。 このようなデータグラムを受信した場合、 返り値は 0 となる。
ストリームソケットに対する受信要求バイト数が 0 だった場合も、 値 0 が返される。
これらはソケット層で発生する一般的なエラーである。 他のエラーが下層のプロトコルモジュールで生成され、 返されるかもしれない。 それらのマニュアルを参照すること。
4.4BSD (これらの関数は 4.2BSD で現われた), POSIX.1-2001。
POSIX.1-2001 では、 MSG_OOB, MSG_PEEK, MSG_WAITALL フラグだけが記載されている。
socklen_t 型は POSIX で発案された。 accept(2) も参照。
POSIX.1-2001 では、構造体 msghdr のフィールド msg_controllen は socklen_t 型であるべきだとされているが、 現在の glibc では size_t 型である。
recvmmsg(2) には、一度の呼び出しでの複数のデータグラムに使用できる Linux 固有の システムコールに関する情報が書かれている。
recvfrom() の利用例が getaddrinfo(3) に記載されている。
fcntl(2), getsockopt(2), read(2), recvmmsg(2), select(2), shutdown(2), socket(2), cmsg(3), sockatmark(3), socket(7)
この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。
2014-08-19 | Linux |