accept() - ソケットに関する新規接続の受け入れ

標準

標準/拡張機能 C/C++ 依存項目

XPG4.2
Single UNIX Specification、バージョン 3

両方  

形式

X/Open:
#define _XOPEN_SOURCE_EXTENDED 1
#include <sys/socket.h>

int accept(int socket, struct sockaddr *__restrict__ address,
           socklen_t *__restrict__address_len);
バークレー・ソケット:
#define _OE_SOCKETS
#include <sys/types.h>
#include <sys/socket.h>

int accept(int socket, struct sockaddr *address, int *address_len);

機能説明

accept() 呼び出しは、サーバーがクライアントからの接続要求を受け入れるのに使用します。接続が使用可能になると、作成されたソケットは、接続要求を行ったプロセスからデータを読み取る準備ができます。呼び出しは、指定のソケット socket 用の保留接続のキューで最初の接続を受け入れます。accept() 呼び出しは socket と同じ特性を持つ新しいソケット記述子を作成して、それを呼び出し元に戻します。キューに保留接続要求がない場合、socket が非ブロック化モードにない限り、accept() は、呼び出し元をブロックします。接続要求がキューに入っていない場合で、socket が非ブロック化モードのときには、accept() は、-1 を戻して、エラー・コードを EWOULDBLOCK に設定します。新しい接続の受け入れに、新しいソケット記述子を 使用することはできません。元のソケットである socket は、今までどおり接続要求を受け入れることができます。
パラメーター
説明
socket
ソケット記述子。
address
accept() が戻る前に、これによって埋められた接続クライアントのソケット・アドレス。address の形式は、クライアントが常駐している ドメインで決定されます。呼び出し元がクライアント・アドレスに関係していない場合、このパラメーターを NULL にすることはできません。
address_len
address が示すストレージのサイズ (バイト) を含む 整数を最初に指す必要があります。戻りの際に、その整数には、接続ソケットのアドレス を表すために必要なサイズが入ります。 この値が、入力のときに提供されたサイズより大きい場合、sockaddr に入っている情報は、入力のときに提供された長さまで切り捨てられます。address が NULL であると、address_len は無視されます。

socket パラメーターは、socket() 呼び出しで作成されるストリーム・ソケット記述子です。これは、通常は bind() 呼び出しを使ってアドレスにバインドされます。listen() 呼び出しは、保留接続要求を保持するために接続を受け入れてキューを割り振るものとして、ソケットにマークを付けます。listen() 呼び出しは、キューのサイズに関して上部境界を設定します。

address パラメーターは、接続リクエスターの アドレスが配置されるバッファーを指すポインターです。address パラメーターはオプション で、NULL ポインターになるように設定することができます。NULL に設定すると、リクエスターのアドレスは バッファーにコピーされません。address の正確な形式は、通信要求の発信元の アドレッシング・ドメインに依存します。例えば、接続要求の発信元が AF_INET ドメインの場合、address は、sockaddr_in 構造体を指し、接続要求の発信元が AF_INET6 ドメインの場合は、address は、sockaddr_in6 構造体を指します。 sockaddr_in および sockaddr_in6 構造体は、 netinet/in.h の中に定義されます。 address_len パラメーターは、address が NULL でない時にのみ使用されます。 accept() を呼び出す前に、address で示されたバッファー・サイズ (バイト) に、address_len で示された整数を設定しなければなりません。正常終了の戻りでは、address_len で示された整数に、バッファーにコピーされた実際のバイト数が入っています。バッファーが、アドレスを保持するのに十分な大きさでない 場合、リクエスターのアドレスの最高 address_len バイトまでがコピーされます。アドレスの実際の長さが、提供される sockaddr を 超える場合、保管されるアドレスは切り捨てられます。保管構造体の sa_len メンバーには、切り捨てられていないアドレスの長さが含まれます。

注 :
  1. この呼び出しは、SOCK_STREAM ソケットだけで使用されます。accept() を呼び出さずにリクエスターを覆う方法はありません。アプリケーションは、接続の受け入れ元となるリクエスターをシステムに 伝えることができません。しかし、呼び出し元はリクエスターの一致を発見した後で、接続を即時にクローズするように選ぶことができます。
  2. accept() 関数は、拡張 ASCII の拡張機能のレベルに依存します。詳細は、拡張 ASCII サポートを参照してください。

select() 呼び出しを使用して、着信接続要求がないかどうかソケットを確認できます。

C++ の特殊な動作: この関数を C++ で使用するには、_XOPEN_SOURCE_EXTENDED 1 フィーチャー・テスト・マクロを使用する必要があります。

戻り値

正常に実行された場合、accept() は、負でないソケット記述子を戻します。

正常に実行されなかった場合、accept() は -1 を戻して、errno を次のいずれかの値に設定します。
エラー・コード
説明
EAGAIN
ID を変更する呼び出しの受け入れ中に新規 ID の UID が 既に MAXPROCUID であれば、その呼び出しの受け入れは失敗します。
EBADF
socket パラメーターが、ソケット記述子の 許容範囲内にありません。
EFAULT
addressaddress_len を使用 した結果、情報を書き込むことができない呼び出し元の アドレス・スペース部分にアドレスをコピーしようとしました。
EINTR
任意の接続が使用可能になる前に、シグナルが accept() 呼び出しに割り込みました。
EINVAL
listen() が、ソケット記述子の socket 用に呼び出されませんでした。
EIO
ネットワークまたはトランスポートで障害が発生しました。
EMFILE
このプロセスに許容されたファイル記述子の最大数を 超えて、オープンしようとしました。
EMVSERR
ID の変更を生じる 2 つの連続した呼び出しの受け入れは許可されません。ID を変更する受け入れがさらに許可されるためには、その前に、元 の ID を復元する (ID の変更を生じたソケットを close() する) 必要があります。
ENFILE
システムのファイル記述子の最大数が 既にオープンしています。
ENOBUFS
新しいソケットを作成するのに 十分なバッファー・スペースが使用できません。
ENOTSOCK
socket パラメーターが有効な ソケット記述子を参照しません。
EOPNOTSUPP
指定されたソケットのソケット・タイプが 接続の受け入れをサポートしません。
EWOULDBLOCK
ソケット記述子の socket が非ブロック化モード であり、キューに接続がありません。

次に、accept() 呼び出しの 2 つの例を示します。最初の例では、呼び出し元はリクエスターのアドレスを 戻そうとしています。次の例では、呼び出し元はリクエスターのアドレスを 戻そうとしていません。
int clientsocket;
int s;
struct sockaddr clientaddress;
int address_len;
int accept(int s, struct sockaddr *addr, int *address_len);
/* socket(), bind(), and listen() 
have been called */
/* EXAMPLE 1: I want the address now */
address_len = sizeof(clientaddress);
clientsocket = accept(s, &clientaddress, &address_len);
/* EXAMPLE 2: I can get the address later using getpeername() */
clientsocket = accept(s, (struct sockaddr *) 0, 
(int *) 0);