len = rc;
rc = send(pass_sd, buffer, len, 0);
if (rc <= 0) {
perror("send() failed");
close(worker_sd);
close(pass_sd);
exit(-1);
}
/*************************************************/
/* Close down the descriptors */
/*************************************************/
close(worker_sd);
close(pass_sd);
}
ソケットのイベントのフロー: 複数の
accept()
ワーカー・ジョブのプールを作成するサーバー 以下のソケット呼び出しのシーケンスは、図の説明となっています。これはまた、サーバーとワーカーの例 の関係の説明ともなっています。それぞれのフローには、特定の API の使用上の注意へのリンクが含まれ ています。特定の API の使用に関する詳細情報は、これらのリンクを使用して参照してください。最初の 例は、以下のソケット呼び出しを使用して子プロセスを作成します。1. socket() API が、端点を表すソケット記述子を戻します。ステートメントは、このソケットのために
INET (インターネット・プロトコル) アドレス・ファミリーと TCP トランスポート (SOCK_STREAM)
を使用することも示します。
2. ソケット記述子が作成された後、bind() API が、ソケットの固有名を取得します。
3. listen() API により、サーバーが着信クライアント接続を受け入れられるようになります。
4. spawn() API が、各ワーカー・ジョブを作成します。
5. この例では、最初の close() API が listen ソケットをクローズします。
ソケットのイベントのフロー
:
複数のaccept()
を使用するワーカー・ジョブ 2 番目の例は、以下の API 呼び出しのシーケンスを使用します。1. サーバーがワーカー・ジョブを spawn した後、このワーカー・ジョブに listen ソケット記述子が、コ マンド行パラメーターとして渡されます。 accept() API が、着信クライアント接続を待機します。
2. recv() API が、クライアントからデータを受信します。
3. send() API が、クライアントにデータを送り返します。
4. close() API が、ワーカー・ジョブを終了します。
関連資料:
119ページの『例: 汎用クライアント』
この例には、共通クライアント・ジョブのコードが含まれています。クライアント・ジョブは、
socket()、connect()、send()、recv()、および close() を実行します。
関連情報:
spawn()
bind()--Set Local Address for Socket API socket()--Create Socket API
listen()--Invite Incoming Connections Requests API close()--Close File or Socket Descriptor API
accept()--Wait for Connection Request and Make Connection API send()--Send Data API
recv()--Receive Data API
例: 複数の accept() ワーカー・ジョブのプールを作成するためのサーバー・プログラム:
以下の例では、複数の accept() モデルを使用して、ワーカー・ジョブをプールを作成する方法を示してい ます。
注: この例の使用をもって、213ページの『コードに関するライセンス情報および特記事項』の条件に同意 したものとします。
/*****************************************************************************/
/* Server example creates a pool of worker jobs with multiple accept() calls */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <spawn.h>
#define SERVER_PORT 12345 main (int argc, char *argv[]) {
int i, num, pid, rc, on = 1;
int listen_sd, accept_sd;
int spawn_fdmap[1];
char *spawn_argv[1];
char *spawn_envp[1];
struct inheritance inherit;
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);
}
/*************************************************/
/* Initialize parameters before entering for loop */
/* */
/* The listen socket descriptor is mapped to */
/* descriptor 0 in the child program. */
/*************************************************/
memset(&inherit, 0, sizeof(inherit));
spawn_argv[0] = NULL;
spawn_envp[0] = NULL;
spawn_fdmap[0] = listen_sd;
/*************************************************/
/* Create each of the worker jobs */
/*************************************************/
printf("Creating worker jobs...\n");
for (i=0; i < num; i++) {
pid = spawn("/QSYS.LIB/QGPL.LIB/WRKR3.PGM", 1, spawn_fdmap, &inherit, spawn_argv, spawn_envp);
if (pid < 0) {
perror("spawn() failed");
close(listen_sd);
exit(-1);
}
printf(" Worker = %d\n", pid);
}
/*************************************************/
/* Inform the user that the server is ready */
/*************************************************/
printf("The server is ready\n");
/*************************************************/
/* Close down the listening socket */
/*************************************************/
close(listen_sd);
}
関連資料:
119ページの『例: 汎用クライアント』
この例には、共通クライアント・ジョブのコードが含まれています。クライアント・ジョブは、
socket()、connect()、send()、recv()、および close() を実行します。
例: 複数の accept() 用のワーカー・ジョブ:
以下の例は、複数の accept() API がワーカー・ジョブを受信し、accept() サーバーを呼び出す方法につい て示します。
注: この例の使用をもって、213ページの『コードに関するライセンス情報および特記事項』の条件に同意 したものとします。
/**************************************************************************/
/* Worker job uses multiple accept() to handle incoming client connections*/
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
main (int argc, char *argv[]) {
int rc, len;
int listen_sd, accept_sd;
char buffer[80];
/*************************************************/
/* The listen socket descriptor is passed to */
/* this worker job as a command line parameter */
/*************************************************/
listen_sd = 0;
/*************************************************/
/* Wait for an incoming connection */
/*************************************************/
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 descriptors */
/*************************************************/
close(listen_sd);
close(accept_sd);
}