/******************************************************************/ /*** server_sel.c ***/ /*** 入力: クライアントからの接続要求 ***/ /*** (7個までのクライアントの接続に対応) ***/ /*** 出力: 約1秒毎に、接続中の全クライアントに対して、 ***/ /*** カウントダウン中のカウンタの値をメッセージとして送信 ***/ /******************************************************************/ #include #include #include #include #include #include #include #define MAX_SOCKS 9 int main() { int s; int ss; int addrlength; char write_buf[1024]; int k; /************************************************************/ /* ソケットを格納する配列 */ /* socks[0] には listening ソケットを格納 */ /* socks[1...(last_socks-1)] には accept したソケットを格納 */ /************************************************************/ int socks[MAX_SOCKS]; int last_socks; /****************************************/ /* 入力のファイル・ディスクリプタの集合 */ /****************************************/ fd_set rfds; /***********************************************************/ /* select() から返ってくるまでの時間の上限を設定する構造体 */ /***********************************************************/ /* struct timeval { */ /* long tv_sec; /* 秒 */ /* long tv_usec; /* マイクロ秒 */ /* }; */ /***********************************************************/ struct timeval tv; /* カウントダウンのためのカウンタ */ int count; /* 時間を計るためのタイマー */ int timer; /***************************************************************/ /* ソケットアドレス UNIX */ /***************************************************************/ /* struct sockaddr_un { */ /* sa_family_t sun_family; /* AF_UNIX */ /* char sun_path[UNIX_PATH_MAX]; /* pathname */ /* }; */ /***************************************************************/ struct sockaddr_un addr; /****************************************/ /* ソケット、通信のための端点の作成 */ /* PF_UNIX: UNIX ローカル通信 */ /* SOCK_STREAM: 順序性と信頼性があり、 */ /* 双方向の、接続された */ /* バ イ ト・ ス ト リーム */ /****************************************/ s = socket(PF_UNIX, SOCK_STREAM, 0); if (s == -1) { printf("Can not create socket.\n"); exit(1); } /******************************/ /* アドレスの設定 */ /* AF_UNIX: UNIX ローカル通信 */ /* 名前: mysocket */ /******************************/ addr.sun_family = AF_UNIX; strcpy(addr.sun_path, "mysocket"); /************************************/ /* ソケットに名前、アドレスを与える */ /************************************/ addrlength = sizeof(addr); if (bind(s, (struct sockaddr *)&addr, addrlength) == -1) { printf("Can not assign the address to a socket.\n"); exit(1); } /****************************/ /* ソケット上の接続を待つ */ /* 接続を待機させる最大数 2 */ /****************************/ if (listen(s, 2) == -1) { printf("Can not listen for connections.\n"); exit(1); } printf("listen...\n"); /****************************************/ /* listening ソケットを socks[0] に格納 */ /****************************************/ last_socks = 0; socks[last_socks] = s; last_socks++; timer = 0; /* タイマーの初期化 */ count = 20; /* カウンタの初期化 */ while (1) { /******************************************************/ /* 入力のファイル・ディスクリプタの集合 rfds を clear */ /******************************************************/ FD_ZERO(&rfds); /*********************************************/ /* 入力のディスクリプタの集合 rfds に */ /* listening ソケット socks[0] と */ /* 接続中の socks[1...(last_socks-1)] を追加 */ /*********************************************/ for (k = 0; k < last_socks; k++) { FD_SET(socks[k], &rfds); } /******************************************************/ /* select から 100000 マイクロ秒で返ってくるように指定 */ /******************************************************/ tv.tv_sec = 0; tv.tv_usec = 100000; /***********************************************************/ /* select システムコール */ /* rfds にリストされた入力のファイル・ディスクリプタを監視 */ /* タイムアウト時間は 100 ミリ秒 */ /***********************************************************/ select(FD_SETSIZE, &rfds, NULL, NULL, &tv); printf("."); /****************************************************************/ /* listening ソケット socks[0] に接続があったかどうかのチェック */ /****************************************************************/ if (FD_ISSET(socks[0], &rfds)) { /* 接続あり */ /* socks[] があふれないかどうかのチェック */ if (last_socks < MAX_SOCKS) { /* あふれない */ /****************************/ /* ソケット上の接続を受ける */ /* 待ちなし */ /****************************/ ss = accept(socks[0], (struct sockaddr *)&addr, &addrlength); printf("\nAccepted... last_socks=%d\n", last_socks); /****************************************/ /* accept したソケットを socks[] に追加 */ /****************************************/ socks[last_socks] = ss; last_socks++; } else { /* socks[] があふれる場合 */ printf("Too many socks. last_socks=%d, MAX_SOCKS=%d\n", last_socks, MAX_SOCKS); break; } } /******************************/ /* 約1秒たったかどうかの確認 */ /******************************/ if (timer == 10) { /* 約1秒たった(100ミリ秒×10)*/ timer = 0; /********************************************************/ /* 接続中の全クライアント socks[1...(last_socks-1)] に */ /* カウントダウン中のカウンタの値をメッセージとして送信 */ /********************************************************/ for (k = 1; k < last_socks; k++) { /****************/ /* write で送信 */ /****************/ sprintf(write_buf, "%d\n", count); printf("write_buf=%s\n", write_buf); ss = socks[k]; write(ss, write_buf, strlen(write_buf)+1); } /*********************************************/ /**** カウンタが0になったかどうかのチェック */ /*********************************************/ if (count == 0) { /* なった */ count = 20; break; } else { count--; } } else { /* まだ1秒たたない */ timer++; } } /**********************/ /* ソケットのクローズ */ /**********************/ shutdown(s, 2); close(s); unlink("mysocket"); }