fork型並行サーバ

Download Report

Transcript fork型並行サーバ

fork型並行サーバ
Python socket module: Just a thin wrapper over the underlying C library's socket calls.
fork型並行サーバ









並行サーバのセッションシーケンス
並行サーバと反復サーバの対比
並行サーバのプロセス作成
並行サーバのプログラムコードの特徴
TCPEchoServer-Fork.c main()
int CreateTCPServerSocket(unsigned short port)
int AcceptTCPConnection(int servSock)
void HandleTCPClient(int clntSocket)
fork型並行サーバPythonプログラム
fork型並行サーバ
並行サーバのセッションシーケンス
クライアント
(接続要求)
並行サー
バ
servSock
クライアント
sock
connect(sock,…)
クライアント
sock
(接続)
サーバ
accept(servSock,…)
servSock
clntSock
servSock
clntSock
クライアント
sock
servSock
clntSock
(データ通信)
クライアント
sock
servSock
clntSock
サーバ
fork()
サーバ:close(clntSock)
子:close(servSock)
サーバ
子:
fork型並行サーバ
反復サーバと並行サーバの対比





反復サーバ(TCPEchoServer.c)は、一度に一つのクラ
イアントのみ処理する。
逐次処理。
並行サーバ(TCPEchoServer-Fork.c)は、プロセスや
スレッドを利用する並行処理。
プロセスやスレッドにより、1つのクライアントの処理を
独立して動作するサーバのコピーを作成。
サーバのコピーが、複数・並行的に動作する。
fork型並行サーバ
並行サーバのプロセス作成



クライアントの要求毎に、fork() システムコールを使っ
て、新しい子プロセスを1つ生成する
fork(): 子プロセスを生成
戻り値: 親:子のプロセスID
戻り値: 子:0
子プロセスは終了後、親プロセスがwaitpid()を呼出す
までゾンビ状態
fork型並行サーバ
並行サーバのプログラムコードの特徴





平行サーバは、クライアントから接続要求がある度
に自身のコピーを作る。
平行サーバの処理は、自身のコピーを作る以外は、
反復サーバと同じ処理を行う。
平行サーバの親プロセスは、クライアント個別との
通信とサービスを処理する、子プロセスをfork()。
親プロセスは、子プロセスをfork()後、クライアント個
別との通信用のソケット(clntSock)を開放する。
一方、子プロセスは、クライアントからのコネクショ
ンを受け付けるためのソケット(servSock)を開放す
る。
fork型並行サーバ
TCPEchoServer-Fork.c main()
#include “TCPEchoServer.h” /* 新しく作ったインクルード */
#include <sys/wait.h>
/* waitpid()で利用する */
int main(int argc, char *argv[])
{
int servSock;
/* サーバのソケット識別子 */
int clntSock;
/* クライアントのソケット識別子 */
unsigned short echoServPort; /* サーバのポート番号 */
pid_t processID;
/* fork()からのプロセスID */
unsigned int childProcCount = 0; /* 子プロセスの数 */
if (argc != 2)
/* 引数の数が正しいかチェック */
{
fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]); /* 第1引数はローカルポート番号 */
servSock = CreateTCPServerSocket(echoServPort);
サーバソケットを
作成
fork型並行サーバ
TCPEchoServer-Fork.c main()
for (;;) /* 永遠に繰返す */
{
clntSock = AcceptTCPConnection(servSock);
接続要求毎に
/* 子プロセスの作成とエラー報告 */
fork()
if ((processID = fork()) < 0)
DieWithError("fork() failed");
else if (processID == 0) /* 子プロセスの場合 */
{
close(servSock); /* 子は親プロセスのソケットをクローズ */
HandleTCPClient(clntSock);
exit(0);
/* 子プロセスの終了 */
クライアント処理
}
を実行
printf("with child process: %d\n", (int) processID);
close(clntSock);
/* 親は子のソケットをクローズ */
childProcCount++;
/* 未回収の子プロセス数を1増やす */
while (childProcCount) /* 全ゾンビをクリーンアップ */
{
processID = waitpid((pid_t) -1, NULL, WNOHANG);
if (processID < 0) /* waitpid()のエラーを確認 */
DieWithError("waitpid() failed");
else if (processID == 0) /* ゾンビが存在しない */
break;
else
childProcCount--; /* 子プロセスを1つ回収 */
}
}
/* この部分には到達しない */
}
ノンブロッキング(ゾンビが
いなければ直に戻る)
fork型並行サーバ
int CreateTCPServerSocket(unsigned short port)
fork型並行サーバ
int AcceptTCPConnection(int servSock)
fork型並行サーバ
void HandleTCPClient(int clntSocket)
fork型並行サーバ
fork型並行サーバPythonプログラム
fork_server.py
socket+os.forkを使ったpreforkサーバ
概説
ソケットを作った後、MAX_PROC個の子プロセスを生成し、
クライアントからの接続を待ちます。
常にMAX_PROC個の子プロセスが生成されており、
同時に処理できるコネクションも子プロセスの数による。
client.py
1connetion client
概説
サーバに1回接続して、文字列送信後、サーバからの文字列
を受信します。
このクライアントを使用して、サーバのテストを行います。
netutil.py
netutil.py
コマンドパラメータの取り出しなど。