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
以下の図は、spawn() サーバー設計が使用される場合に、サーバー、ワーカー、およびクライアント・ジョ ブが対話する方法を示しています。
ソケットのイベントのフロー: spawn() を使用して要求を受け入れ処理するサーバー
以下のソケット呼び出しのシーケンスは、図の説明となっています。これはまた、サーバーとワーカーの例 の関係の説明ともなっています。それぞれのフローには、特定の API の使用上の注意へのリンクが含まれ ています。特定の API の使用に関する詳細情報は、これらのリンクを使用して参照してください。最初の 例は、以下のソケット呼び出しを使用して、spawn() API 呼び出しで子プロセスを作成します。
1. socket() API が、端点を表すソケット記述子を戻します。ステートメントは、このソケットのために
INET (インターネット・プロトコル) アドレス・ファミリーと TCP トランスポート (SOCK_STREAM)
を使用することも示します。
2. ソケット記述子が作成された後、bind() API が、ソケットの固有名を取得します。
3. listen() により、サーバーが着信クライアント接続を受け入れられるようになります。
4. サーバーは、着信接続要求を受け入れるために accept() API を使用します。 accept() 呼び出しは、着 信接続を待機して、無期限にブロックします。
5. spawn() API が、着信要求を処理するワーカー・ジョブのパラメーターを初期設定します。この例で は、新規接続のソケット記述子が子プログラムの記述子 0 にマップされます。
6. この例では、最初の close() API が listen ソケット記述子をクローズします。 2 番目の close () 呼び 出しは、受け入れたソケットを終了します。
ソケットのイベントのフロー
: spawn()
によって作成されるワーカー・ジョブ 2 番目の例は、以下の API 呼び出しのシーケンスを使用します。1. サーバーで spawn() API が呼び出されると、recv() API が着信接続からデータを受信します。
2. send() API が、クライアントにデータを送り返します。
3. close() API が、spawn されたワーカー・ジョブを終了します。
関連資料:
119ページの『例: 汎用クライアント』
この例には、共通クライアント・ジョブのコードが含まれています。クライアント・ジョブは、
socket()、connect()、send()、recv()、および close() を実行します。
関連情報:
spawn()
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 close()--Close File or Socket Descriptor API
send()--Send Data API recv()--Receive Data API
例: spawn() を使用するサーバーの作成:
以下の例では、spawn() API を使用して、親プロセスからソケット記述子を継承する子プロセスを作成する 方法を示しています。
注: この例の使用をもって、213ページの『コードに関するライセンス情報および特記事項』の条件に同意 したものとします。
/**************************************************************************/
/* Application creates an child process using spawn(). */
/**************************************************************************/
#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;
addr.sin6_port = htons(SERVER_PORT);
memcpy(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any));
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");
/**********************************************/
/* Initialize the spawn parameters */
/* */
/* The socket descriptor for the new */
/* connection is mapped over to descriptor 0 */
/* in the child program. */
/**********************************************/
memset(&inherit, 0, sizeof(inherit));
spawn_argv[0] = NULL;
spawn_envp[0] = NULL;
spawn_fdmap[0] = accept_sd;
/**********************************************/
/* Create the worker job */
/**********************************************/
printf(" creating worker job\n");
pid = spawn("/QSYS.LIB/QGPL.LIB/WRKR1.PGM", 1, spawn_fdmap, &inherit, spawn_argv, spawn_envp);
if (pid < 0) {
perror("spawn() failed");
close(listen_sd);
close(accept_sd);
exit(-1);
}
printf(" spawn completed successfully\n");
/**********************************************/
/* Close down the incoming connection since */
/* it has been given to a worker to handle */
/**********************************************/
close(accept_sd);
}
/*************************************************/
/* Close down the listen socket */
/*************************************************/
close(listen_sd);
}
関連資料:
106ページの『例: ワーカー・ジョブがデータ・バッファーを受信できるようにする』
この例には、ワーカー・ジョブがクライアント・ジョブからデータ・バッファーを受け取るようにし、これ をそのまま戻すためのコードが含まれています。
例: ワーカー・ジョブがデータ・バッファーを受信できるようにする:
この例には、ワーカー・ジョブがクライアント・ジョブからデータ・バッファーを受け取るようにし、これ をそのまま戻すためのコードが含まれています。
注: この例の使用をもって、213ページの『コードに関するライセンス情報および特記事項』の条件に同意 したものとします。
/**************************************************************************/
/* Worker job that receives and echoes back a data buffer to a client */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
main (int argc, char *argv[]) {
int rc, len;
int sockfd;
char buffer[80];
/*************************************************/
/* The descriptor for the incoming connection is */
/* passed to this worker job as a descriptor 0. */
/*************************************************/
sockfd = 0;
/*************************************************/
/* Receive a message from the client */
/*************************************************/
printf("Wait for client to send us a message\n");
rc = recv(sockfd, buffer, sizeof(buffer), 0);
if (rc <= 0) {
perror("recv() failed");
close(sockfd);
exit(-1);
}
printf("<%s>\n", buffer);
/*************************************************/
/* Echo the data back to the client */
/*************************************************/
printf("Echo it back\n");
len = rc;
rc = send(sockfd, buffer, len, 0);
if (rc <= 0) {
perror("send() failed");
close(sockfd);
exit(-1);
}
/*************************************************/
/* Close down the incoming connection */
/*************************************************/
close(sockfd);
}
関連資料:
103ページの『例: spawn() を使用するサーバーの作成』
以下の例では、spawn() API を使用して、親プロセスからソケット記述子を継承する子プロセスを作成する 方法を示しています。