- 締切済み
チャットプログラムでのselectの使い方について
linux開発環境でC言語を用いて1対5程度のチャットプログラムを作成しています。クライアントから送信された内容はサーバに表示されるのですが、この内容を他のクライアントにも表示したいです。そこでselect関数を用いたいのですが、どこにどのようなコードで挿入すればよいかわかりません。以下にプログラムを載せるので、できれば詳しいコードで回答をよろしくお願いいたします。 サーバプログラム #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/wait.h> #include <unistd.h> #include <signal.h> #include <netdb.h> #define PORT 5320 void kill_zombie_process(int sig); void close_process(int unused); char *show_ip(char *ip_address); int main(void) { int soc, acc, size; char buffer[80]; struct sockaddr_in client, server; struct hostent *server_host; pid_t pid; char host_name[257]; int temp; memset(host_name, 0, sizeof(host_name)); gethostname(host_name, 256); server_host = gethostbyname(host_name); printf("\n-------- informations of server ----------\n"); printf("Host name:%s\n", host_name); printf("IP = %s\n", show_ip(server_host->h_addr)); printf("\n\n"); soc = socket(AF_INET, SOCK_STREAM, 0); memset((char *)&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); bind(soc, (struct sockaddr *)&server, sizeof(server)); size = sizeof(client); listen(soc, 5); signal(SIGINT, close_process); signal(SIGCHLD, kill_zombie_process); while(1) { acc = accept(soc, (struct sockaddr *)&client, &size); pid = fork(); if(pid == 0) { close(soc); while(1) { memset(buffer, '\0', sizeof(buffer)); recv(acc, buffer, 80, 0); printf("%s> ", show_ip((char *)&client.sin_addr)); printf("%s", buffer); if(strncmp(buffer, "exit", 4) == 0) break; } close(acc); exit(0); } else { close(acc); } } return 0; } void kill_zombie_process(int sig) { while(waitpid(-1, NULL, WNOHANG) > 0); signal(SIGCHLD, kill_zombie_process); } void close_process(int unused) { exit(0); } char *show_ip(char *ip_address) { static char ip[7]; char ipnum[4]; bcopy(ip_address, ipnum, 4); sprintf(ip, "%u.%u.%u.%u",(unsigned char)ipnum[0], (unsigned char)ipnum[1], (unsigned char)ipnum[2],(unsigned char)ipnum[3]); return ip; } クライアントプログラム #include<stdio.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #define PORT 5320 int main(int argc, char *argv[]) { int soc; char message[80],ip_address[16]; struct sockaddr_in server; if(argc == 1) { printf("引数にIPアドレスが必要です/n"); exit(0); } strcpy(ip_address,argv[1]); soc = socket(AF_INET,SOCK_STREAM,0); memset((char *)&server,0,sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(PORT); server.sin_addr.s_addr = inet_addr(ip_address); connect(soc,(struct sockaddr *)&server,sizeof(server)); while(1) { printf("メッセージを入力してください:"); fgets(message,80,stdin); send(soc,message,strlen(message),0); if(strncmp(message,"exit",4) == 0)break; } close(soc); return 0; }
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- k-841
- ベストアンサー率27% (129/465)
select()を使うというアイデアはいいですが、サーバプログラムでaccept()したものをfork()してしまうということは、接続してきたクライアント一つ一つに対応してサーバプロセスが切り離されて起動されてしまうことになるため、あまりよろしくありません(不可能ではないですが・・・)。select()は、複数のソケットなりファイルデスクリプタなりのいずれかからイベントが発生したことをキャッチすることができます。まずはfork()しないプログラミングを考えてみてください。