前提・実現したいこと
select関数を用いて同期I/Oの多重化を検証する課題を行っています。
単純なechoback関数を用いて通信のやり取りを行うのですが、今サーバー側プログラムの
制作で詰まっています。
以下echoback処理のサーバー側のサンプルプログラムとクライアント側のプログラム、そして今回使うselect関数によるデータ通信プログラムを掲載してあります。
発生している問題・エラーメッセージ
改めて困っている内容は、サンプルではselect関数を用いた通信プログラムの下のほうでechoback関数を使っているのですが、そのechoback関数の実装ないので方法を知りたいです。
簡潔に言うと以下のserver.cを参考にselect.cのechoback関数を実装したいというところでしょうか。
server.c
1 #include "exp1.h" 2 #include "exp1lib.h" 3 4 int main(int argc, char** argv) { 5 int sock_listen; 6 int sock_client; 7 struct sockaddr addr; 8 int len = 0; 9 int ret = 0; 10 char buf[1024]; 11 12 sock_listen = exp1_tcp_listen(11111); 13 sock_client = accept(sock_listen, &addr, (socklen_t*) &len); 14 ret = recv(sock_client, buf, 1024, 0); 15 write(1, buf, ret); 16 send(sock_client, buf, ret, 0); 17 close(sock_client); 18 close(sock_listen); 19 20 return 0; 21 }
client.c
1 #include "exp1.h" 2 #include "exp1lib.h" 3 4 int main(int argc, char** argv) { 5 int sock; 6 char* p; 7 char buf[1024]; 8 int ret; 9 10 if(argc != 2) { 11 printf("usage: %s [ip address]\n", argv[0]); 12 exit(-1); 13 } 14 15 sock = exp1_tcp_connect(argv[1], 11111); 16 p = fgets(buf, 1024, stdin); 17 send(sock, p, strlen(p), 0); 18 ret = recv(sock, buf, sizeof(buf), 0); 19 write(1, buf, ret); 20 close(sock); 21 22 return 0; 23 }
select.c
1#define MAXCHILD 1200 2void acceptLoop(int sock) { 3 4 // クライアント管理 5 int childNum = 0; 6 int child[MAXCHILD]; 7 int i = 0; 8 for (i = 0; i < MAXCHILD; i++) { 9 child[i] = -1; 10 } 11 12 while (true) { 13 14 // select用マスクの初期化 15 fd_set mask; 16 FD_ZERO(&mask); 17 FD_SET(sock, &mask); 18 int width = sock + 1; 19 int i = 0; 20 for (i = 0; i < childNum; i++) { 21 if (child[i] != -1) { 22 FD_SET(child[i], &mask); 23 if ( width <= child[i] ) { 24 width = child[i] + 1; 25 } 26 } 27 } 28 29 // マスクを設定 30 fd_set ready = mask; 31 32 // タイムアウト値のセット 33 struct timeval timeout; 34 timeout.tv_sec = 600; 35 timeout.tv_usec = 0; 36 37 switch (select(width, (fd_set *) &ready, NULL, NULL, &timeout)) { 38 case -1: 39 // エラー処理 40 perror("select"); 41 break; 42 case 0: 43 // タイムアウト 44 break; 45 default: 46 // I/Oレディあり 47 48 if (FD_ISSET(sock, &ready)) { 49 // サーバソケットレディの場合 50 struct sockaddr_storage from; 51 socklen_t len = sizeof(from); 52 int acc = 0; 53 if ((acc = accept(sock, (struct sockaddr *) &from, &len)) 54 == -1) { 55 // エラー処理 56 if (errno != EINTR) { 57 perror("accept"); 58 } 59 } else { 60 // クライアントからの接続が行われた場合 61 char hbuf[NI_MAXHOST]; 62 char sbuf[NI_MAXSERV]; 63 getnameinfo((struct sockaddr *) &from, len, hbuf, 64 sizeof(hbuf), sbuf, sizeof(sbuf), 65 NI_NUMERICHOST | NI_NUMERICSERV); 66 fprintf(stderr, "accept:%s:%s\n", hbuf, sbuf); 67 68 // クライアント管理配列に登録 69 int pos = -1; 70 int i = 0; 71 for (i = 0; i < childNum; i++) { 72 if (child[i] == -1) { 73 pos = i; 74 break; 75 } 76 } 77 78 if (pos == -1) { 79 if (childNum >= MAXCHILD) { 80 // 並列数が上限に達している場合は切断する 81 fprintf(stderr, "child is full.\n"); 82 close(acc); 83 } else { 84 pos = childNum; 85 childNum = childNum + 1; 86 } 87 } 88 89 if (pos != -1) { 90 child[pos] = acc; 91 } 92 } 93 } 94 95 // アクセプトしたソケットがレディの場合を確認する 96 int i = 0; 97 for (i = 0; i < childNum; i++) { 98 if (child[i] != -1 && FD_ISSET(child[i], &ready)) { 99 // クライアントとの通信処理 100 if ( echoBack(child[i]) == false ) { 101 close(child[i]); 102 child[i] = -1; 103 } 104 } 105 } 106 } 107 } 108}
あなたの回答
tips
プレビュー