この例では、すべての着信接続を処理する単一のサーバー・ジョブを作成する方法を示します。accept() API が完了すると、サーバーがトランザクション全体を処理します。
以下の図は、システムが反復サーバー設計を使用する場合に、サーバー・ジョブとクライアント・ジョブが 対話する方法を示しています。
ソケットのイベントのフロー: 反復サーバー
以下のソケット呼び出しのシーケンスは、図の説明となっています。これはまた、サーバー・アプリケーシ ョンとワーカー・アプリケーションの関係の説明ともなっています。それぞれのフローには、特定の API
の使用上の注意へのリンクが含まれています。特定の API の使用に関する詳細な説明を参照するために、
これらのリンクを使用できます。以下のシーケンスは、反復サーバー・アプリケーション用の API 呼び出 しを示しています。
1. socket() API が、端点を表すソケット記述子を戻します。ステートメントは、このソケットのために
INET (インターネット・プロトコル) アドレス・ファミリーと TCP トランスポート (SOCK_STREAM)
を使用することも示します。
2. ソケット記述子が作成された後、bind() API が、ソケットの固有名を取得します。
3. listen() により、サーバーが着信クライアント接続を受け入れられるようになります。
4. サーバーは、着信接続要求を受け入れるために accept() API を使用します。 accept() 呼び出しは、着 信接続を待機して、無期限にブロックします。
5. recv() API が、クライアント・アプリケーションからデータを受信します。
6. send() API が、クライアントにデータを送り返します。
7. close() API が、オープンしているソケット記述子をすべてクローズします。
注: この例の使用をもって、213ページの『コードに関するライセンス情報および特記事項』の条件に同意 したものとします。
/**************************************************************************/
/* Application creates an iterative server design */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SERVER_PORT 12345 main (int argc, char *argv[]) {
int i, len, num, rc, on = 1;
int listen_sd, accept_sd;
char buffer[80];
struct sockaddr_in6 addr;
/*************************************************/
/* If an argument was specified, use it to */
/* control the number of incoming connections */
/*************************************************/
if (argc >= 2)
num = atoi(argv[1]);
else num = 1;
/*************************************************/
/* Create an AF_INET6 stream socket to receive */
/* incoming connections on */
/*************************************************/
listen_sd = socket(AF_INET6, SOCK_STREAM, 0);
if (listen_sd < 0) {
perror("socket() failed");
exit(-1);
}
/*************************************************/
/* Allow socket descriptor to be reuseable */
/*************************************************/
rc = setsockopt(listen_sd,
SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
if (rc < 0) {
perror("setsockopt() failed");
close(listen_sd);
exit(-1);
}
/*************************************************/
/* Bind the socket */
/*************************************************/
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
addr.sin6_port = htons(SERVER_PORT);
rc = bind(listen_sd,
(struct sockaddr *)&addr, sizeof(addr));
if (rc < 0) {
perror("bind() failed");
close(listen_sd);
exit(-1);
}
/*************************************************/
/* Set the listen back log */
/*************************************************/
rc = listen(listen_sd, 5);
if (rc < 0) {
perror("listen() failed");
close(listen_sd);
exit(-1);
}
/*************************************************/
/* Inform the user that the server is ready */
/*************************************************/
printf("The server is ready\n");
/*************************************************/
/* Go through the loop once for each connection */
/*************************************************/
for (i=0; i < num; i++) {
/**********************************************/
/* Wait for an incoming connection */
/**********************************************/
printf("Interation: %d\n", i+1);
printf(" waiting on accept()\n");
accept_sd = accept(listen_sd, NULL, NULL);
if (accept_sd < 0) {
perror("accept() failed");
close(listen_sd);
exit(-1);
}
printf(" accept completed successfully\n");
/**********************************************/
/* Receive a message from the client */
/**********************************************/
printf(" wait for client to send us a message\n");
rc = recv(accept_sd, buffer, sizeof(buffer), 0);
if (rc <= 0) {
perror("recv() failed");
close(listen_sd);
close(accept_sd);
exit(-1);
}
printf(" <%s>\n", buffer);
/**********************************************/
/* Echo the data back to the client */
/**********************************************/
printf(" echo it back\n");
len = rc;
rc = send(accept_sd, buffer, len, 0);
if (rc <= 0) {
perror("send() failed");
close(listen_sd);
close(accept_sd);
exit(-1);
}
/**********************************************/
/* Close down the incoming connection */
/**********************************************/
close(accept_sd);
}
/*************************************************/
/* Close down the listen socket */
/*************************************************/
close(listen_sd);
}
関連資料:
119ページの『例: 汎用クライアント』
この例には、共通クライアント・ジョブのコードが含まれています。クライアント・ジョブは、
socket()、connect()、send()、recv()、および close() を実行します。
関連情報:
recv()--Receive Data API
bind()--Set Local Address for Socket API socket()--Create Socket API
listen()--Invite Incoming Connections Requests API
accept()--Wait for Connection Request and Make Connection API send()--Send Data API
close()--Close File or Socket Descriptor API