tail head cat sleep
QR code linking to this page

manページ  — RECV

名称

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 * restrict 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 が返され、外部変数 errnoEAGAIN に設定されます。 通常、受信呼び出しは要求された量を受信するまで待たずに、 要求された量を上限として得られたデータを返します。 この動作は、 getsockopt(2) で解説されているソケットレベルのオプション SO_RCVLOWAT および SO_RCVTIMEO によって影響を受けます。

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

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

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

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_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[]; が後に続く */
};

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

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

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

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

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 はソケットを参照していません。
[EMSGSIZE]
  recvmsg() システムコールは、接続時にデータをやりとりする権利 (ファイル記述子) を受信するために使用されました。 しかしながら、受信プログラムには受け付けるための 空きファイル記述子スロットがありませんでした。 この場合、記述子がクローズされ、 recvmsg() への別の呼び出しによって、 どんなペンディング (未解決) のデータも返すことができます。
[EAGAIN]
  ソケットが非ブロッキングとマークされているとき、 受信操作でブロックしました。 あるいは、受信タイムアウトが設定されていて、 データが受信される前にタイムアウトになりました。
[EINTR]
  データが受信可能になる前に、受信がシグナルによって割込まれました。
[EFAULT]
  受信バッファポインタが、プロセスに割り当てられたアドレス空間の 範囲外を指しています。

関連項目

fcntl(2), getsockopt(2), read(2), select(2), socket(2)

歴史

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

RECV (2) February 21, 1994

tail head cat sleep
QR code linking to this page


このマニュアルページサービスについてのご意見は Ben Bullock にお知らせください。 Privacy policy.

Not only is UNIX dead, it's starting to smell really bad.
— Rob Pike