fork()を使ったマルチクライアント型プログラム


マルチクライアント型のサーバーを作成する場合、fork()システムコールを使って プロセスを分けて しまうこともできます。つまり、親プロセスではクライアントからの接続要求 だけを処理し、実際のクライアントの処理は子プロセスに任せてしまうのです。 今回の並行サーバーのプログラムには、

        if ((pid = fork()) < 0) {
            perror("fork");
            exit(1);
        } else if (pid == 0) {
            /* fork()で新しく生成されたプロセスはこちら */
            close(fd1);
            ret = read(fd2, buf, 1024);
            while (strcmp(buf, "quit\n") != 0) {
                /* bufの中の小文字を大文字に変換する */
                for (i=0; i< ret; i++) {
                    if (isalpha(buf[i]))
                        buf[i] = toupper(buf[i]);
                }   
                /* 変換したデータをクライアントに送り返す */
                write(fd2, buf, 1024);
                ret = read(fd2, buf, 1024);
            }
            exit(0);
        }

という処理が追加されています。 このプログラムでは、acceptシステムコールによりクライアントからの接続要 求を受け入れると、まずfork()システムコールを実行します。fork()システム コールの返り値が負の数ならば、失敗しているので終了します。

fork()システムコールの返り値(pidの値)が0となるのは、子プロセスの場合で す。子プロセスでは、クライアントからの接続を受け入れるためのファイルディ スクリプタfd1をクローズします。これは、子プロセスでは新たな接続要求を 受け付けないためです。そして、accect()システムコールにより返された、クラ イアントと接続されているファイルディスクリプタを用いて、大文字への変換 作業を行います。

一方、親プロセスでは、fork()システムコールから返ってきた直後にfd2をク ローズします。このファイルディスクリプタに関しては、子プロセスに処理を 依頼しており、親プロセス自身で処理する必要がないためです。その後、ルー プの先頭に戻り、再度accept()システムコールを実行して、別のクライアント が接続してくるのを待ちます。

クライアントプログラムは、これまでに使ってきた、iclient.c とまったく同じです。