前提・実現したいこと
C言語で非同期のチャットプログラムを作りたいのです。
コンパイルできたのですが実行できません。原因と解決方法を知りたいです。
該当のソースコード
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #define BUFSIZE 256 #define SOCK_MAX 4 #define UNUSED (-1) void chop(char* str) { char* p = strchr(str, '\n'); if (p != NULL) *p = '\0'; } int main(int argc, char *argv[]) { int sockets[6]; // socketの配列,自分用,クライアント用,拒否用 fd_set readfds; struct sockaddr_in server; // サーバプロセスのソケットアドレス情報 struct sockaddr_in client; // クライアントプロセスのソケットアドレス情報 socklen_t fromlen; // クライアントプロセスのソケットアドレス情報の長さ uint16_t port; // ポート番号 char buffer[BUFSIZE]; // メッセージを格納するバッファ int temp = 1; int i, max; int numrcv; if (argc != 2) { fprintf(stderr, "Usage: %s <port>\n", argv[0]); exit(EXIT_FAILURE); } fromlen = sizeof(client); port = atoi(argv[1]); for(i=0;i<6;i++) sockets[i] = UNUSED; sockets[0] = socket(PF_INET, SOCK_STREAM, 0); if (sockets[0] == -1) { perror("server: socket"); exit(EXIT_FAILURE); } // サーバプロセスのソケットアドレス情報の設定 memset((void *) &server, 0, sizeof(server)); // アドレス情報構造体の初期化 server.sin_family = PF_INET; // プロトコルファミリの設定 server.sin_port = htons(port); // ポート番号の設定 server.sin_addr.s_addr = htonl(INADDR_ANY); // ソケットにアドレスをバインド if (bind(sockets[0], (struct sockaddr *) &server, sizeof(server)) == -1) { perror("server: bind"); exit(EXIT_FAILURE); } // 接続要求の受け入れ準備 // バインドされたソケットを待機状態に if (listen(sockets[0], SOCK_MAX + 1) == -1) { perror("server: listen"); exit(EXIT_FAILURE); } max = 1; // クライアントと接続されているソケットへデータ送信 while (1) { // readfds の 初期化 FD_ZERO(&readfds); for(i=0;i<max;i++){ if(sockets[i] != UNUSED) FD_SET(sockets[i], &readfds); } if(select(FD_SETSIZE, &readfds, NULL, NULL, NULL) == -1){ perror("select"); exit(EXIT_FAILURE); } for(i=1;i<max;i++){ if(sockets[i] != UNUSED){ if(FD_ISSET(sockets[i],&readfds)){ // データ受信準備 memset(buffer, '\0', BUFSIZE); // データ送信 recv(sockets[i], buffer, BUFSIZE,0); printf("from client: %s\n", buffer); if (strcmp(buffer, "quit") == 0){ int status = close(sockets[i]); sockets[i] = UNUSED; } printf("received (%d) : %s\n",i,buffer); } } } if(FD_ISSET(sockets[0],&readfds)){ printf("Accept New connection.\n"); for(i = 1;i<max;i++){ if(sockets[i] == UNUSED) break; } sockets[i] = accept(sockets[0], (struct sockaddr *) &client, &fromlen); for (i = 1; i < max; i++) { if (sockets[i] != UNUSED) { if (FD_ISSET(sockets[i], &readfds)) { // データ受信準備 memset(buffer, '\0', BUFSIZE); printf(">: %s\n", buffer); // データ送信 if (fgets(buffer, BUFSIZE, stdin) == NULL) strcpy(buffer, "quit"); chop(buffer); send(sockets[i], buffer, BUFSIZE, 0); if (strcmp(buffer, "quit") == 0) { int status = close(sockets[i]); sockets[i] = UNUSED; } printf("received (%d) : %s\n", i, buffer); } } } if(i<SOCK_MAX +1){ printf("client accepted (%d)\n",i); if(i == max) { max++; }else{ for(;max>0;max--){ if(sockets[max-1] != UNUSED) break; } } }else{ printf("refuse connection.\n"); strcpy(buffer,"Server is too busy.\n"); send(sockets[i],buffer,strlen(buffer),0); close(sockets[i]); } } } return 0; }//サーバー側 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #define BUFSIZE 256 #define SOCK_MAX 4 #define UNUSED (-1) void chop(char* str) { char* p = strchr(str, '\n'); if (p != NULL) *p = '\0'; } int main(int argc, char* argv[]) { int sockets[6]; // socketの配列,自分用,クライアント用,拒否用 fd_set readfds; struct sockaddr_in server; // サーバプロセスのソケットアドレス情報 struct sockaddr_in client; // クライアントプロセスのソケットアドレス情報 socklen_t fromlen; // クライアントプロセスのソケットアドレス情報の長さ uint16_t port; // ポート番号 char buffer[BUFSIZE]; // メッセージを格納するバッファ int temp = 1; int i, max; int numrcv; if (argc != 3) { fprintf(stderr, "Usage: %s <port>\n", argv[0]); exit(EXIT_FAILURE); } fromlen = sizeof(server); port = atoi(argv[1]); for (i = 0; i < 6; i++) sockets[i] = UNUSED; sockets[0] = socket(PF_INET, SOCK_STREAM, 0); if (sockets[0] == -1) { perror("server: socket"); exit(EXIT_FAILURE); } // サーバプロセスのソケットアドレス情報の設定 memset((void*)&client, 0, sizeof(client)); // アドレス情報構造体の初期化 server.sin_family = PF_INET; // プロトコルファミリの設定 server.sin_port = htons(port); // ポート番号の設定 server.sin_addr.s_addr = htonl(INADDR_ANY); // ソケットにアドレスをバインド if (bind(sockets[0], (struct sockaddr*) & server, sizeof(server)) == -1) { perror("server: bind"); exit(EXIT_FAILURE); } // 接続要求の受け入れ準備 // バインドされたソケットを待機状態に if (listen(sockets[0], SOCK_MAX + 1) == -1) { perror("server: listen"); exit(EXIT_FAILURE); } max = 1; // クライアントと接続されているソケットへデータ送信 while (1) { // readfds の 初期化 FD_ZERO(&readfds); for (i = 0; i < max; i++) { if (sockets[i] != UNUSED) FD_SET(sockets[i], &readfds); } if (select(FD_SETSIZE, &readfds, NULL, NULL, NULL) == -1) { perror("select"); exit(EXIT_FAILURE); } for (i = 1; i < max; i++) { if (sockets[i] != UNUSED) { if (FD_ISSET(sockets[i], &readfds)) { // データ受信準備 memset(buffer, '\0', BUFSIZE); printf(">: %s\n", buffer); // データ送信 if (fgets(buffer, BUFSIZE, stdin) == NULL) strcpy(buffer, "quit"); chop(buffer); send(sockets[i], buffer, BUFSIZE, 0); if (strcmp(buffer, "quit") == 0) { int status = close(sockets[i]); sockets[i] = UNUSED; } printf("received (%d) : %s\n", i, buffer); } } } if (FD_ISSET(sockets[0], &readfds)) { printf("Accept New connection.\n"); for (i = 1; i < max; i++) { if (sockets[i] == UNUSED) break; } sockets[i] = accept(sockets[0], (struct sockaddr*) & server, &fromlen); for (i = 1; i < max; i++) { if (sockets[i] != UNUSED) { if (FD_ISSET(sockets[i], &readfds)) { // データ受信準備 memset(buffer, '\0', BUFSIZE); recv(sockets[i], buffer, BUFSIZE, 0); // データ送信 if (strcmp(buffer, "quit") == 0) { int status = close(sockets[i]); sockets[i] = UNUSED; } printf("received (%d) : %s\n", i, buffer); } } } if (i < SOCK_MAX + 1) { printf("client accepted (%d)\n", i); if (i == max) { max++; } else { for (; max > 0; max--) { if (sockets[max - 1] != UNUSED) break; } } } else { printf("refuse connection.\n"); strcpy(buffer, "Server is too busy.\n"); send(sockets[i], buffer, strlen(buffer), 0); close(sockets[i]); } } } return 0; }//クライアント側