これらの改良には,WEBページ「UNIXソケットプログラミング入門 (1)」と 「ネットワークプログラミング」を参考にしている.不明 な部分は,このページを見ると良いだろう.
1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/types.h> 4 #include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 8 int main(int argc, char *argv[]) 9 { 10 struct sockaddr_in server; 11 char message[80], ip_address[16]; 12 int fd; 13 14 strcpy(ip_address,argv[1]); // コマンドライン引数のIPアドレスのコピー 15 fd=socket(PF_INET, SOCK_STREAM, 0); // ソケットの作成 16 17 memset((char *) &server, 0, sizeof(server)); // アドレス構造体の初期化 18 server.sin_family=AF_INET; 19 server.sin_port = htons(5320); 20 server.sin_addr.s_addr=inet_addr(ip_address); 21 connect(fd, (struct sockaddr *) &server, sizeof(server)); 22 23 24 while(1){ 25 printf("message:"); 26 fgets(message, 80, stdin); 27 send(fd, message, strlen(message),0); 28 if(strncmp(message,"bye",3)==0)break; 29 } 30 31 close(fd); 32 33 return 0; 34 }
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <sys/socket.h> 7 #include <netinet/in.h> 8 #include <sys/wait.h> 9 #include <arpa/inet.h> 10 #include <unistd.h> 11 #include <signal.h> 12 #include <netdb.h> 13 14 #define PORT 5320 15 16 void kill_zombie(int sig); 17 void close_process(int unused); 18 char *showip(char *ip_address); 19 20 //=========================================================================== 21 // main 関数 22 //============================================================================ 23 int main(void) 24 { 25 struct sockaddr_in client, server; 26 struct hostent *server_host; 27 int fds, fda, length; 28 pid_t pid; 29 char host_name[257]; 30 31 int temp; 32 33 // --- 自ホスト情報の取得と表示 ----- 34 bzero(host_name,257); 35 gethostname(host_name,256); // 自ホスト名の取得 36 server_host = gethostbyname(host_name); // 自ホスト情報の取得 37 printf("\n-------- informations of server ----------\n"); 38 printf("Host name:%s\n",host_name); // 自ホスト名の表示 39 printf("IP= %s\n",showip(server_host->h_addr)); // IPアドレスを表示 40 printf("\n\n"); 41 42 fds=socket(PF_INET, SOCK_STREAM, 0); // ソケット作製 43 44 memset((char *) &server, 0, sizeof(server)); // ゼロで埋める 45 server.sin_family=AF_INET; 46 server.sin_addr.s_addr = inet_addr(showip(server_host->h_addr)); 47 server.sin_port = htons(PORT); 48 bind(fds, (struct sockaddr *) &server, sizeof(server)); // ソケットに名前 49 50 listen(fds, 5); 51 52 53 54 length=sizeof(client); 55 56 signal(SIGINT, close_process); // [Ctrl]+cを押したとき 57 signal(SIGCHLD, kill_zombie); // 子プロセスの監視 58 59 while(1){ // 無限ループ 60 61 fda=accept(fds, (struct sockaddr *) &client, &length); 62 63 pid=fork(); 64 65 if(pid==0){ //----- 子プロセス -------------- 66 char read_str[80]; // データ読み込み領域 67 close(fds); // ソケットをクローズ 68 while(1){ // 無限ループ 69 memset(read_str, '\0', sizeof(read_str)); // 文字列の終わりを示す'\0'で埋める 70 recv(fda, read_str, 80, 0); // データの受信 71 printf("%s> ",showip((char *)&client.sin_addr)); // クライアントアドレス表示 72 printf("%s",read_str); // 受信データーを表示 73 if(strncmp(read_str,"bye",3)==0)break; // "bye"ならば,ループ脱出 74 } 75 close(fda); // ファイルディスクリプタをクローズ 76 exit(0); // 子プロセス終了 77 }else{ //----- 親プロセス -------------- 78 close(fda); // ファイルディスクリプタークローズ 79 } 80 } 81 82 return 0; 83 } 84 85 //================================================================== 86 // ゾンビの埋葬 以下を参考 87 // http://hp.vector.co.jp/authors/VA003991/kouza/senior/kouza_socket.html 88 //================================================================== 89 void kill_zombie(int sig){ 90 while(waitpid(-1,NULL,WNOHANG)>0); 91 signal(SIGCHLD, kill_zombie); 92 } 93 94 //================================================================== 95 // [Ctrl]+cが押されたときの処理 まだ作成途中 96 //================================================================== 97 void close_process(int unused){ 98 exit(0); 99 } 100 101 //================================================================== 102 // IPアドレスのポインターを返す 103 //================================================================== 104 char *showip(char *ip_address) 105 { 106 static char ip[7]; // 静的変数.メモリーから消えない 107 char ipnum[4]; 108 109 bcopy(ip_address, ipnum, 4); 110 sprintf(ip,"%u.%u.%u.%u", // %u:符号なし10進数 111 (unsigned char)ipnum[0], 112 (unsigned char)ipnum[1], 113 (unsigned char)ipnum[2], 114 (unsigned char)ipnum[3]); 115 116 return ip; 117 }
子プロセス(実行中のプログラム)とは,親プロセスから呼び出されたプロセスである. fork()システムコールを使うと,呼び出した親プロセスと以下の部分のみが異なる 子プロセスができる.
fork()システムコールを実行すると,現在のプロセスのコピーが作成される.全く 同じ二つのプロセスが実行されることになる.一つは親プロセス,もう一つは子プロセス である.同じプログラムではあるが,データ空間は異なる.そのため,親と子では異なっ た動作をさせることができる.
親と子のプロセスの区別は,fork()の戻り値で区別できる.親の戻り値は子プロセ スのプロセスID(正の整数)で,子プロセスは0である.fork()の戻り値 が-1の場合,子プロセスの生成の失敗を示す.
次の例が最も簡単な,子プロセスを使ったプログラムである.
#include <stdio.h> #include <stdlib.h> // exit()を使うため #include <sys/types.h> // fork()を使うため #include <unistd.h> // fork()を使うため int main(void) { int pid; int i=8,j=3; pid=fork(); if(pid==0){ // -------- 子プロセス ------------- printf("child process\n"); printf("i+j=%d\n",i+j); exit(0); }else{ // -------- 親プロセス ------------- printf("parent process\n"); printf("i-j=%d\n",i-j); } return 0; }
child process i+j=11 parent process i-j=5