Network プログラムの例

  1. HTTP ポートの利用例(本文のプログラム例 19.1 参照)

    ------------------------- c_setup.cpp -------------------------
    
    /******************************************/
    /* ソケットの初期設定(クライアント)     */
    /*      return : ソケットのディスクリプタ */
    /******************************************/
    #include <stdio.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <netdb.h>   // ソケット(hostent等)
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    #include <unistd.h>   // fork, read, write, open, close
    
    //int c_setup(char *hostname, in_port_t port)
    int c_setup(char *hostname, int port)    // コンパイラのバージョンによっては,
                                               // 上の行の代わりにこの行を使用
    {
    	int client_socket = -1;   // ソケット
    	hostent *server_inf1;   // サーバ情報1
    	sockaddr_in server_inf2;   // サーバ情報2
    /*
    		サーバ名からサーバ情報を得る
    */
    	if ((server_inf1 = gethostbyname(hostname)) == NULL)
    		printf("***error***  サーバ名が不適当です\n");
    /*
    		サーバ情報をsockaddr_in構造体に設定
    */
    	else {
    		memset((char *)&server_inf2, 0, sizeof(server_inf2));
    		server_inf2.sin_family      = AF_INET;   // アドレスファミリー
    		server_inf2.sin_port        = htons(port);   // htons(2バイト)
                                                         //   整数の上位及び下位バイトの指定
    		memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr,
                   server_inf1->h_length);
    /*
    		ソケットを作成
    */
    		if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    			printf("***error***  socketを作成できませんでした\n");
    /*
    		サーバへ接続
    */
    		else {
    			if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1)
    				client_socket = -1;
    		}
    	}
    
    	return client_socket;
    }
    
    ------------------------- html.cpp (main) -------------------------
    
    /****************************/
    /* HTTPクライアント     */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>   // fork, read, write, open, close
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    #define BUF_LEN 512   // バッファサイズ
    #define PORT 80   // ポート番号
    
    //int c_setup(char *, in_port_t);
    int c_setup(char *, int);    // コンパイラのバージョンによっては,
                                   // 上の行の代わりにこの行を使用
    
    int main(int argc, char *argv[])
    {
    	int n;
    	int client_socket;   // 送受信用のソケット
    	char buf[BUF_LEN];   // 送受信用バッファ
    	char hostname[50] = "cs-www";   // ホスト名
    	char adr[100] = "/~suganuma/index.html";   // ファイル名
    	char buf1[20];
    /*
    		初期設定
    */
    	if ((client_socket = c_setup(hostname, PORT)) == -1) {
    		printf("***error***  接続できませんでした\n");
    		exit(1);
    	}
    /*
    		サーバとの送信
    */
    	else {
    					// 送信内容の指定(サーバに対するリクエスト)
    		strcpy(buf, "GET ");
    		strcat(buf, adr);
    		strcat(buf, " HTTP/1.1\r\n");
    		write(client_socket, buf, strlen(buf));
    					// ホスト名とポート
    		strcpy(buf, "Host: ");
    		strcat(buf, hostname);
    		strcat(buf, ":");
    		gcvt((double)PORT, 10, buf1);
    		strcat(buf, buf1);
    		strcat(buf, "\r\n");
    		write(client_socket, buf, strlen(buf));
    					// リクエスト(GET)の終了
    		strcpy(buf, "\r\n");
    		write(client_socket, buf, strlen(buf));
    					// 受信内容の表示
    		n = 1;
    		while (n > 0) {
    			n = read(client_socket, buf, BUF_LEN);
    			if (n > 0)
    				write(1, buf, n);
    		}
    	}
    
    	close(client_socket);
    
    	return 0;
    }
    			

  2. ファイルの転送例(本文のプログラム例 19.2 参照)

    クライアント側のプログラム

    ------------------------- c_setup.cpp -------------------------
    
    /******************************************/
    /* ソケットの初期設定(クライアント)     */
    /*      hostname : サーバ名               */
    /*      port : ポート番号                 */
    /*      return : ソケットのディスクリプタ */
    /******************************************/
    #include <stdio.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <netdb.h>   // ソケット(hostent等)
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    int c_setup(char *hostname, in_port_t port)
    //int c_setup(char *hostname, int port)    // コンパイラのバージョンによっては,
                                               // 上の行の代わりにこの行を使用
    {
    	int client_socket = -1;   // ソケット
    	hostent *server_inf1;   // サーバ情報1
    	sockaddr_in server_inf2;   // サーバ情報2
    /*
    		サーバ名からサーバ情報を得る
    */
    	if ((server_inf1 = gethostbyname(hostname)) == NULL)
    		printf("***error***  サーバ名が不適当です\n");
    /*
    		サーバ情報をsockaddr_in構造体に設定
    */
    	else {
    		memset((char *)&server_inf2, 0, sizeof(server_inf2));
    		server_inf2.sin_family      = AF_INET;   // アドレスファミリー
    		server_inf2.sin_port        = htons(port);   // htons(2バイト)
                                                         //   整数の上位及び下位バイトの指定
    		memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr,
                   server_inf1->h_length);
    /*
    		ソケットを作成
    */
    		if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    			printf("***error***  socketを作成できませんでした\n");
    /*
    		サーバへ接続
    */
    		else {
    			if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1)
    				client_socket = -1;
    		}
    	}
    /*
    		ディスクリプタを返す
    */
    	return client_socket;
    }
    
    ------------------------- client1.cpp (main) -------------------------
    
    /********************************/
    /* ファイル転送(クライアント) */
    /*      coded by Y.Suganuma     */
    /********************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <fcntl.h>   // O_RDONLY等
    #include <unistd.h>   // fork, read, write, open, close
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    #define BUF_LEN 512   // バッファサイズ
    #define PORT 50000   // ポート番号
    
    int c_setup(char *, in_port_t);
    //int c_setup(char *, int);    // コンパイラのバージョンによっては,
                                   // 上の行の代わりにこの行を使用
    
    int main(int argc, char *argv[])
    {
    	int n, sw, in;
    	int client_socket;   // 送受信用のソケット
    	char buf[BUF_LEN];   // 送受信用バッファ
    	char hostname[50];   // ホスト名
    /*
    		サーバ名
    */
    	if (argc != 2) {
    		printf("***error***  サーバ名を入力してください\n");
    		exit(1);
        }
    	else
    		strcpy(hostname, argv[1]);
    /*
    		初期設定
    */
    	if ((client_socket = c_setup(hostname, PORT)) == -1) {
    		printf("***error***  接続できませんでした\n");
    		exit(1);
    	}
    /*
    		ファイル名の入力とファイル内容の転送
    */
    					// ファイル名の入力
    	n = read(client_socket, buf, BUF_LEN);
    	write(1, buf, n);
    	scanf("%s", buf);
    					// ファイル名の送信
    	in = open(buf, O_RDONLY);
    //	in = open(buf, O_BINARY | O_RDONLY);
    //    OS(MS-DOSなど)によっては,上の行の代わりにこの行を使用しないと
    //    バイナリファイルを正しく送信できない.
    	if (in < 0) {
    		printf("***error***  ファイルが存在しません\n");
    		close(client_socket);
    		exit(1);
    	}
    	write(client_socket, buf, strlen(buf)+1);
    					// ファイル内容の送信
    	sw = 1;
    	while (sw > 0) {
    		n = read(in, buf, BUF_LEN);
    		if (n > 0)
    			write(client_socket, buf, n);
    		else
    			sw = 0;
    	}
    /*
    		接続を切り,ファイルを閉じる
    */
    	close(client_socket);
    	close(in);
    
    	return 0;
    }
    			

    サーバ側のプログラム

    ------------------------- s_setup.cpp -------------------------
    
    /************************************/
    /* ソケットの初期設定(サーバ)     */
    /*      port : ポート番号           */
    /*      return : リスニングソケット */
    /************************************/
    #include <stdio.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <arpa/inet.h>   // ソケット(sockaddr_in等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    int s_setup(in_port_t port)
    //int s_setup(int port)    // コンパイラのバージョンによっては,
                               // 上の行の代わりにこの行を使用
    {
    	int listening_socket = -1;   // リスニングソケット
    	sockaddr_in server_inf;   // サーバ情報
    /*
    		サーバ情報をsockaddr_in構造体に設定
    */
    	memset((char *)&server_inf, 0, sizeof(server_inf));
    	server_inf.sin_family      = AF_INET;   // アドレスファミリー
    	server_inf.sin_addr.s_addr = htonl(INADDR_ANY);   // IPアドレス
    	server_inf.sin_port        = htons(port);   // htonl(4バイト),htons(2バイト)
                                                    //   整数の上位及び下位バイトの指定
    /*
    		リスニングソケットを作成
    */
    	if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    		printf("***error***  接続できませんでした\n");
    /*
    		サーバのアドレスをソケットに設定する
    */
    	else {
    	    if (bind(listening_socket, (sockaddr *)&server_inf, sizeof(server_inf)) < 0)
    			printf("***error***  設定に失敗しました\n");
    /*
    		待ち受ける(待機状態の準備)(第2引数は,待ち受けの数)
    */
    		else {
    			if (listen(listening_socket, 1) == -1 )
    				printf("***error***  待ち受けに失敗しました\n");
    		}
    	}
    
    	return listening_socket;
    }
    
    ------------------------- e_ftp.cpp -------------------------
    
    /********************************************/
    /* ftpの実行                                */
    /*      connected_socket : 接続済みソケット */
    /********************************************/
    #include <stdio.h>
    #include <fcntl.h>   // O_RDONLY等
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netdb.h>   // ソケット(inet_ntoa等)
    #include <arpa/inet.h>   // ソケット(sockaddr_in等)
    #include <unistd.h>   // fork, read, write, open, close
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    #define BUF_LEN 512   // バッファサイズ
    
    void e_ftp(int connected_socket)
    {
    	int n, sw, out;
    	char buf[BUF_LEN];   // 送受信用バッファ
    	hostent *client_inf1;   // クライアント情報1
    	sockaddr_in client_inf2;   // クライアント情報2
    	socklen_t len;
    //	int len;    // コンパイラのバージョンによっては,
                    // 上の行の代わりにこの行を使用
    /*
    		クライアント情報を取得できた場合,それを表示する
    */
    	len = (socklen_t)sizeof(client_inf2);
    //	len = sizeof(client_inf2);    // コンパイラのバージョンによっては,
                                      // 上の行の代わりにこの行を使用
    	getpeername(connected_socket, (sockaddr *)&client_inf2, &len);
    	client_inf1 = gethostbyaddr((char *)&client_inf2.sin_addr.s_addr,
                                                    sizeof(client_inf2.sin_addr), AF_INET);
    	if (client_inf1 != NULL) {
    		printf("%s と接続しました(IP: %s, ポート %d)\n",
                    client_inf1->h_name, inet_ntoa(client_inf2.sin_addr),
                    ntohs(client_inf2.sin_port));
    	}
    /*
    		送られてきたファイルを保存
    */
    					// ファイル名
    	write(connected_socket, "ファイル名を入力してください ", 29);
    	read(connected_socket, buf, BUF_LEN);
    					// 保存
    	out = open(buf, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
    //	out = open(buf, O_BINARY | O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
    //    OS(MS-DOSなど)によっては,上の行の代わりにこの行を使用しないと,
    //    バイナリファイルを正しく送信できない.
    	sw  = 1;
    	while (sw > 0) {
    		n = read(connected_socket, buf, BUF_LEN);
    		if (n > 0)
    			write(out, buf, n);
    		else
    			sw = 0;
    	}
    
    	close(out);
    }
    
    ------------------------- server1.cpp (main) -------------------------
    
    /****************************/
    /* ファイル転送(サーバ)   */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    #include <unistd.h>   // fork, read, write, open, close
    
    #define PORT 50000   // ポート番号
    
    int s_setup(in_port_t);
    //int s_setup(int);    // コンパイラのバージョンによっては,
                           // 上の行の代わりにこの行を使用
    void e_ftp(int);
    
    int main()
    {
    	int listening_socket;   // リスニングソケット
    	int connected_socket;   // 接続済みソケット
    	pid_t pid;   // プロセスID
    /*
    		リスニングソケットの生成
    */
    	if ((listening_socket = s_setup(PORT)) != -1) {
    /*
    		接続待機
    */
    		while(1) {
    					// 接続済みソケット
    			if ((connected_socket = accept(listening_socket, NULL, NULL)) != -1) {
    					// 子プロセスの生成
    						// 子プロセス
    				if ((pid = fork()) == 0) {
    					close(listening_socket);
    					e_ftp(connected_socket);
    					close(connected_socket);
    					exit(0);
    				}
    						// 親プロセス
    				else
    					close(connected_socket);
    			}
    		}
    	}
    
    	return 0;
    }
    			

  3. チャットルーム(本文のプログラム例 19.3 参照)

    クライアント側のプログラム

    ------------------------- c_setup.cpp -------------------------
    
    /******************************************/
    /* ソケットの初期設定(クライアント)     */
    /*      hostname : サーバ名               */
    /*      port : ポート番号                 */
    /*      return : ソケットのディスクリプタ */
    /******************************************/
    #include <stdio.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <netdb.h>   // ソケット(hostent等)
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    int c_setup(char *hostname, in_port_t port)
    //int c_setup(char *hostname, int port)    // コンパイラのバージョンによっては,
                                               // 上の行の代わりにこの行を使用
    {
    	int client_socket = -1;   // 送受信用のソケット
    	hostent *server_inf1;   // サーバ情報1
    	sockaddr_in server_inf2;   // サーバ情報2
    /*
    		サーバ名からサーバ情報を得る
    */
    	if ((server_inf1 = gethostbyname(hostname)) == NULL)
    		printf("***error***  サーバ名が不適当です\n");
    /*
    		サーバ情報をsockaddr_in構造体に設定
    */
    	else {
    		memset((char *)&server_inf2, 0, sizeof(server_inf2));
    		server_inf2.sin_family      = AF_INET;   // アドレスファミリー
    		server_inf2.sin_port        = htons(port);   // htons(2バイト)
                                                         //   整数の上位及び下位バイトの指定
    		memcpy((char *)&server_inf2.sin_addr.s_addr, server_inf1->h_addr,
                   server_inf1->h_length);
    /*
    		ソケットを作成
    */
    		if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    			printf("***error***  socketを作成できませんでした\n");
    /*
    		サーバへ接続
    */
    		else {
    			if (connect(client_socket, (sockaddr *)&server_inf2, sizeof(server_inf2)) == -1)
    				client_socket = -1;
    		}
    	}
    /*
    		ディスクリプタを返す
    */
    	return client_socket;
    }
    
    ------------------------- prepare.cpp -------------------------
    
    /***************************************/
    /* 会話のための準備                    */
    /*      soc : ソケットのディスクリプタ */
    /*      return : select用初期化マスク  */
    /***************************************/
    #include <sys/types.h>   // fd_set
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    
    fd_set prepare(int soc)
    {
    	fd_set mask;
    /*
    		マスクの準備
    */
    	FD_ZERO(&mask);
    	FD_SET(0, &mask);   // ディスクリプタ0(キーボード)をセット
    	FD_SET(soc, &mask);   // ソケットのディスクリプタをセット
    
    	return mask;
    }
    
    ------------------------- chat.cpp -------------------------
    
    /**************************************/
    /* 会話                               */
    /*      fd : ソケットのディスクリプタ */
    /*      buf : バッファ                */
    /*      size : バッファサイズ         */
    /*      mask : select用初期化マスク   */
    /**************************************/
    #include <stdio.h>
    #include <sys/types.h>   // fd_set
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <unistd.h>   // fork, read, write, open, close
    
    void chat(int fd, char *buf, int size, fd_set mask)
    {
    	int n, sw = 1;
    	fd_set now;
    
    	while (sw > 0) {
    					// マスクの初期化
    		now = mask;
    		select(fd+1, (fd_set*)&now, NULL, NULL, NULL);
    					// キーボードからの入力チェック
    		if (FD_ISSET(0, &now)) {
    			gets(buf);
    			n = strlen(buf);
    			if (n > 0)
    				write(fd, buf, n);   // 送信
    		}
    					// ソケット内のデータを調べる
    		if (FD_ISSET(fd, &now)) {
    			n      = read(fd, buf, size);
    			buf[n] = '\0';
    			if (strcmp(buf, "Server.quit") == 0) {
    				printf("チャットルームを閉じます!\n");
    				close(fd);
    				sw = 0;
    			}
    			else if (strcmp(buf, "quit") == 0) {
    				close(fd);
    				sw = 0;
    			}
    			else
    				write(1, buf, n);
    		}
    	}
    }
    
    ------------------------- client2.cpp (main) -------------------------
    
    /**********************************/
    /* チャットルーム(クライアント) */
    /*      coded by Y.Suganuma       */
    /**********************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>   // fd_set
    #include <unistd.h>   // fork, read, write, open, close
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    #define BUF_LEN 512   // バッファサイズ
    #define PORT 50000   // ポート番号
    
    void chat(int, char *, int, fd_set);
    fd_set prepare(int);
    int c_setup(char *, in_port_t);
    //int c_setup(char *, int);    // コンパイラのバージョンによっては,
                                   // 上の行の代わりにこの行を使用
    
    int main(int argc, char *argv[])
    {
    	int n;
    	int client_socket;   // 送受信用のソケット
    	char buf[BUF_LEN];   // 送受信用バッファ
    	char hostname[50];   // ホスト名
    	fd_set mask;   // 相手を選択する(select)ための初期化マスク
    /*
    		サーバ名
    */
    	if (argc != 2) {
    		printf("***error***  サーバ名を入力してください\n");
    		exit(1);
        }
    	else
    		strcpy(hostname, argv[1]);
    /*
    		初期設定
    */
    	if ((client_socket = c_setup(hostname, PORT)) == -1) {
    		printf("***error***  接続できませんでした\n");
    		exit(1);
    	}
    /*
    		参加登録
    */
    	n = read(client_socket, buf, BUF_LEN);   // 参加者名の入力を促すメッセージ
    	write(1, buf, n);
    	buf[n] = '\0';
    
    	if (strstr(buf, "満員ですので,後ほどご利用下さい") != NULL)
    		close(client_socket);
    
    	else {
    		gets(buf);   // 参加者名の入力
    		write(client_socket, buf, strlen(buf)+1);
    		n = read(client_socket, buf, BUF_LEN);   // 「しばらくお待ち下さい」
    		write(1, buf, n);
    					// サーバとクライアントが会話を行うための準備(マスクの設定)
    		mask = prepare(client_socket);
    					// チャットの実行
    		chat(client_socket, buf, BUF_LEN, mask);
    	}
    
    	return 0;
    }
    			

    サーバ側のプログラム

    ------------------------- member.h -------------------------
    
    /**************/
    /* 参加者情報 */
    /**************/
    class Member {
    	public:
    		int state;   // 回線の状態(1 : 開, 0 : 閉)
    		int fd;   // ソケットディスクリプタ
    		char name[50];   // 参加者名
    		Member();   // コンストラクタ
    };
    
    ------------------------- Member.cpp -------------------------
    
    /********************************/
    /* クラスmemberのコンストラクタ */
    /********************************/
    #include "member.h"
    
    Member::Member()
    {
    	state = 0;
    }
    
    ------------------------- s_setup.cpp -------------------------
    
    /************************************/
    /* ソケットの初期設定(サーバ)     */
    /*      port : ポート番号           */
    /*      w_no : 待ち受けの最大数     */
    /*      return : リスニングソケット */
    /************************************/
    #include <stdio.h>
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    
    int s_setup(in_port_t port, int w_no)
    //int s_setup(int port, int w_no)
    	// コンパイラのバージョンによっては,上の行の代わりにこの行を使用
    {
    	int listening_socket = -1;   // リスニングソケットソケット
    	sockaddr_in server_inf;   // サーバ情報
    /*
    		サーバ情報をsockaddr_in構造体に設定
    */
    	memset((char *)&server_inf, 0, sizeof(server_inf));
    	server_inf.sin_family      = AF_INET;   // アドレスファミリー
    	server_inf.sin_addr.s_addr = htonl(INADDR_ANY);   // IPアドレス
    	server_inf.sin_port        = htons(port);   // htonl(4バイト),htons(2バイト)
                                                    //   整数の上位及び下位バイトの指定
    /*
    		リスニングソケットを作成
    */
    	if ((listening_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    		printf("***error***  接続できませんでした\n");
    /*
    		サーバのアドレスをソケットに設定する
    */
    	else {
    	    if (bind(listening_socket, (sockaddr *)&server_inf, sizeof(server_inf)) < 0)
    			printf("***error***  設定に失敗しました\n");
    /*
    		待ち受ける(待機状態の準備)(第2引数は,待ち受けの数)
    */
    		else {
    			if (listen(listening_socket, w_no) == -1 )
    				printf("***error***  待ち受けに失敗しました\n");
    		}
    	}
    
    	return listening_socket;
    }
    
    ------------------------- init.cpp -------------------------
    
    /************************************/
    /* 参加者の登録と初期設定           */
    /*      soc : 接続済みソケット      */
    /*      w_no : 待ち受けの最大数     */
    /*      mask : select用初期化マスク */
    /*      no : 現在の接続数           */
    /*      mem : 接続登録簿            */
    /*      return : 現在の接続数       */
    /************************************/
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/types.h>   // fd_set
    #include <unistd.h>   // read, write, open, close
    #include "member.h"
    
    int init(int soc, int w_no, fd_set *mask, int no, Member **mem)
    {
    	int i1, sw = 0;
    					// 満員
    	if (no == w_no) {
    		write(soc, "満員ですので,後ほどご利用下さい\n", 33);
    		close(soc);
    	}
    					// 参加できる
    	else {
    		for (i1 = 0; i1 < w_no && sw == 0; i1++) {
    			if (mem[i1]->state == 0) {
    						// ディスクリプタの登録
    				mem[i1]->state = 1;
    				mem[i1]->fd    = soc;
    				no++;
    						// マスクの設定
    				FD_SET(mem[i1]->fd, mask);
    						// 参加者名
    				write(soc, "名前を入力して下さい ", 21);
    				read(soc, mem[i1]->name, 50);
    				strcat(mem[i1]->name, ": ");
    						// 開始OK
    				write(soc, "しばらくお待ち下さい\n", 21);
    				write(soc, "チャット開始OKです!\n", 23);
    				sw = 1;
    			}
    		}
    	}
    
    	return no;
    }
    
    ------------------------- chat.cpp -------------------------
    
    /**********************************************/
    /* チャットの実行                             */
    /*      w_no : 待ち受けの最大数               */
    /*      max_fd : ソケットの最大ディスクリプタ */
    /*      buf : バッファ                        */
    /*      size : バッファサイズ                 */
    /*      mask : select用初期化マスク           */
    /*      no : 現在の接続数                     */
    /*      mem : 各ソケットの状態                */
    /*      listening_socket : リスニングソケット */
    /**********************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>   // fd_set
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <unistd.h>   // read, write, open, close
    #include "member.h"
    
    #define BUF_LEN_TMP 562   // バッファの大きさ
    
    int init(int, int, fd_set *, int, Member **);
    
    int chat(int w_no, int *max_fd, char *buf, int size, fd_set *mask,
             int no, Member **mem, int listening_socket)
    {
    	int i1, i2, k, len, n, sw = 1;
    	char str[BUF_LEN_TMP];
    	int connected_socket;   // 接続済みソケット
    	fd_set now;
    					// マスクの初期化と事象の選択
    	now = *mask;
    	select((*max_fd)+1, (fd_set *)&now, NULL, NULL, NULL);
    					// 新規のクライアント登録
    	if (FD_ISSET(listening_socket, &now)) {
    		if ((connected_socket = accept(listening_socket, NULL, NULL)) != -1) {
    			k = init(connected_socket, w_no, mask, no, mem);
    			if (k > no) {
    				no = k;
    				if (connected_socket > *max_fd)
    					*max_fd = connected_socket;
    			}
    		}
    		else {
    			printf("***error***  クライアントとの接続に失敗しました\n");
    			exit(1);
    		}
    	}
    					// チャットの終了チェック
    	if (FD_ISSET(0, &now)) {   // キーボードからの入力チェック
    		gets(buf);
    		if (strcmp(buf, "quit") == 0) {
    			for (i1 = 0; i1 < w_no; i1++) {
    				if (mem[i1]->state > 0)
    					write(mem[i1]->fd, "Server.quit", 11);
    			}
    			for (i1 = 0; i1 < w_no; i1++) {
    				if (mem[i1]->state > 0)
    					close(mem[i1]->fd);
    			}
    			for (i1 = 0; i1 < w_no; i1++)
    				delete [] mem[i1];
    			delete [] mem;
    			sw = 0;
    			no = -1;
    		}
    	}
    					// 各ソケットを調べる
    	if (sw > 0) {
    		for (i1 = 0; i1 < w_no; i1++) {
    			if (mem[i1]->state > 0 && FD_ISSET(mem[i1]->fd, &now)) {
    				n      = read(mem[i1]->fd, buf, size);
    				buf[n] = '\0';
    						// クライアントの終了
    				if (strcmp(buf, "quit") == 0) {
    					write(mem[i1]->fd, "また参加して下さい!\n", 21);
    					write(mem[i1]->fd, "quit", 4);
    					FD_CLR(mem[i1]->fd, mask);
    					close(mem[i1]->fd);
    					mem[i1]->state = 0;
    					*max_fd        = -1;
    					for (i2 = 0; i2 < w_no; i2++) {
    						if (mem[i2]->state > 0 && mem[i2]->fd > *max_fd)
    							*max_fd = mem[i2]->fd;
    					}
    					no--;
    				}
    						// チャットの続行
    				else {
    					len = strlen(mem[i1]->name);
    					strcpy(str, mem[i1]->name);
    					strcat(str, buf);
    					strcat(str, "\n");
    					for (i2 = 0; i2 < w_no; i2++) {
    						if (mem[i2]->state > 0)
    							write(mem[i2]->fd, str, n+len+1);
    					}
    				}
    			}
    		}
    	}
    
    	return no;
    }
    
    ------------------------- server2.cpp (main) -------------------------
    
    /****************************/
    /* チャットルーム(サーバ) */
    /*      coded by Y.Suganuma */
    /****************************/
    #include <stdio.h>
    #include <stdlib.h>   // atoi等
    #include <string.h>   // 文字列操作,memset,FD_ZERO等
    #include <sys/types.h>   // fd_set
    #include <sys/socket.h>   // ソケット(AF_INET, select等)
    #include <netinet/in.h>    // in_port_t, sockaddr_in等
    #include <unistd.h>   // read, write, open, close
    #include "member.h"
    
    #define PORT 50000   // ポート番号
    #define BUF_LEN 512   // バッファの大きさ
    
    int chat(int, int *, char *, int, fd_set *, int, Member **, int);
    int s_setup(in_port_t, int);
    //int s_setup(int, int);
    	// コンパイラのバージョンによっては,上の行の代わりにこの行を使用
    
    int main(int argc, char *argv[])
    {
    	int i1, no = 0, max = 0, sw = 1;
    	char buf[BUF_LEN];   // バッファ
    	int listening_socket;   // リスニングソケットソケット
    	int max_fd;   // 接続済みソケットの最大ディスクリプタ
    	fd_set mask;
    	Member **mem;
    /*
    		最大参加者数
    */
    	if (argc != 2) {
    		printf("***error***  参加者数を入力してください\n");
    		exit(1);
        }
    	else
    		max = atoi(argv[1]);
    /*
    		リスニングソケットの準備
    */
    	if ((listening_socket = s_setup(PORT, max)) == -1) {
    		printf("***error***  リスニング接続に失敗しました\n");
    		exit(1);
    	}
    /*
    		参加登録簿とマスクの準備
    */
    	mem = new Member * [max];
    	for (i1 = 0; i1 < max; i1++)
    		mem[i1] = new Member;
    
    	max_fd = listening_socket;
    	FD_ZERO(&mask);
    	FD_SET(0, &mask);   // ディスクリプタ0(キーボード)をセット
    	FD_SET(listening_socket, &mask);   // リスニングソケットをセット
    /*
    		チャットの実行
    */
    	printf("Ready to Chat\n");
    
    	while (sw > 0) {
    		no = chat(max, &max_fd, buf, BUF_LEN, &mask, no, mem, listening_socket);
    		if (no < 0) {
    			sw = 0;
    			close(listening_socket);
    		}
    	}
    
    	return 0;
    }