これらの改良には,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