• 検索結果がありません。

例: 反復サーバー・プログラムの作成

ドキュメント内 rzab6pdf.ps (ページ 104-107)

この例では、すべての着信接続を処理する単一のサーバー・ジョブを作成する方法を示します。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

ドキュメント内 rzab6pdf.ps (ページ 104-107)