エコーサーバの改良�

 前回で、エコーサーバがクライアントからの入力に何度でも応答を返すように改良をしました。しかし、未だに問題点があります。複数のクライアントからの入力に対応できていないのです。

 実際に試してみるとすぐわかるのですが、クライアントAがエコーサーバにアクセスしているときは、別のクライアントBはエコーサーバに接続はできても、応答が返ってきません。そこで今回は、複数のクライアントからの接続にも対応できるようにします。

ソースコード

//echo_main.cのファイル
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

int echo_main(int sock){

        char buf[32];
        int n;
        memset(buf, 0, sizeof(buf));
//ここから
        int pid;
        pid = fork();
        if (pid  == 0){
                while( n = read(sock, buf, sizeof(buf)) != -1){
                        write(sock, buf, strlen(buf));
                }
        }
//ここまで
        return 0;
}
//main.cのファイル
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>

#include "server.h"

int main(void){

        struct sockaddr_in client;
        int sock,sockfd;
        int len = sizeof(client);

        sockfd = listened_socket();
//ここから
        for(;;){
        sock = accept(sockfd, (struct sockaddr *) &client, &len);
                echo_main(sock);
        }
//ここまで
        close(sock);

        return 0;
}

 main関数では、accept関数からecho_main関数までを無限ループで囲み、echo_main関数ではreadおよびwrite関数をforkで分岐させました。

解説

 異なるクライアントからアクセスが来るたびにfork()関数で処理が分岐されます。子プロセスではエコーサーバとして、クライアントからの入力を返します。親プロセスでは、echo_main関数を終了して、main関数に戻り、無限ループ内で別のクライアントからの接続に備えます。
 この結果、netstatコマンドでa.outという名前のプロセスが増えていくのが確認できます。以下はローカルの2つのtelnetからアクセスした結果です。

# netstat -apn |grep 80の結果
1 tcp        0      0 0.0.0.0:80           0.0.0.0:*               LISTEN      11309/a.out
2 tcp        0      0 127.0.0.1:80         127.0.0.1:59014         ESTABLISHED 11309/a.out
3 tcp        0      0 127.0.0.1:80         127.0.0.1:59013         ESTABLISHED 11309/a.out
4 tcp        0      0 127.0.0.1:59013         127.0.0.1:80         ESTABLISHED 11310/telnet
5 tcp        0      0 127.0.0.1:59014         127.0.0.1:89         ESTABLISHED 11312/telnet

1 待ち受け中のa.outのプロセス。
2 一つ目のtelnetのプロセスに対応して分岐したa.outのプロセス。
3 二つ目のtelnetのプロセスに対応して分岐したa.outのプロセス。
4,5 telnetのプロセス。

このループだと、acceptのループになっている可能性がある。要再チェック。
子プロセスのゾンビ対策がなされていない。