http://ash.jp/net/prog_net.htm
上記のWebページに掲載されているC言語版の"hellosv.c","hellocl.c","makefile"を同一のディレクトリ下にダウンロードし、"make all"を実行したところ以下のようなエラーが発生し上手くコンパイルすることができません。
cc -o hellosv hellosv.c -lsocket -lnsl -dn
cc1: 警告: 認識できない gcc デバッグオプション: n
hellosv.c: In function ‘main’:
hellosv.c:45: 警告: incompatible implicit declaration of built-in function ‘bzero’
hellosv.c:48: 警告: incompatible implicit declaration of built-in function ‘memcpy’
hellosv.c:50: 警告: passing argument 2 of ‘bind’ from incompatible pointer type
/usr/include/sys/socket.h:115: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_in *’
hellosv.c:66: 警告: passing argument 2 of ‘accept’ from incompatible pointer type
/usr/include/sys/socket.h:214: note: expected ‘struct sockaddr * __restrict__’ but argument is of type ‘struct sockaddr_in *’
hellosv.c:85: 警告: incompatible implicit declaration of built-in function ‘exit’
/usr/bin/ld: cannot find -lsocket
collect2: ld はステータス 1 で終了しました
make: *** [hellosv] エラー 1
解決方法をご教示いただけないでしょうか?
本気で勉強するなら、以下を薦めておきます。
UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI
とりあえず修正してみました。FreeBSDとdebian で動いています。
% cc -Wall -o hellosv hellosv.c % cc -Wall -o hellosv hellocl.c %
/* */ /* コネクション型のサーバプログラム (hellosv.c) */ /* Usage: hellosv host_name & */ /* */ #include <stdio.h> #include <netdb.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define PROT_NO 5001 static char mesg[] = "Hello world."; static struct sockaddr_in sv_addr; /* サーバアドレス */ static struct sockaddr_in cl_addr; /* クライアントアドレス */ static struct hostent *sv_ip; /* サーバIPアドレス */ static int sid1; /* デーモンソケット識別子 */ static int sid2; /* 子プロセスソケット識別子 */ static int cl_size; /* クライアントアドレスサイズ */ /* サーバメイン */ int main(argc, argv) int argc; char *argv[]; /* argv[1]:サーバホスト名 */ { int rtn; /* 返却値 */ /* コネクション型ソケットの作成 (socket) */ sid1 = socket(AF_INET, SOCK_STREAM, 0); if (sid1 < 0) { perror("sv:socket"); goto err; } /* サーバのIPアドレスを取得 */ sv_ip = gethostbyname(argv[1]); if (sv_ip == NULL) { perror("sv:gethostbyname"); goto err; } /* ソケットに名前を付加 (bind) */ bzero((char *)&sv_addr, sizeof(sv_addr)); sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(PROT_NO); memcpy((char *)&sv_addr.sin_addr, (char *)sv_ip->h_addr, sv_ip->h_length); rtn = bind(sid1, (struct sockaddr *)&sv_addr, sizeof(sv_addr)); if (rtn < 0) { perror("sv:bind"); goto err; } /* クライアントからの接続要求の受付 (listen) */ rtn = listen(sid1, 5); if (rtn == -1) { perror("sv:listen"); goto err; } while (1) { /* クライアントからの接続要求の受信 (accept) */ cl_size = sizeof(cl_addr); sid2 = accept(sid1, (struct sockaddr *)&cl_addr, (socklen_t *)&cl_size); if (sid2 < 0) { perror("sv:accept"); goto err; } /* メッセージ通信処理 (send/recv) */ rtn = send(sid2, mesg, sizeof(mesg), 0); if (rtn < 0) perror("sv:send"); /* ソケットの開放 (shutdown,close) */ rtn = shutdown(sid2, 2); if (rtn < 0) perror("sv:shutdown"); close(sid2); } err: /* ソケットの開放 (close) */ close(sid1); exit(0); }
/* */ /* コネクション型クライアントプログラム (hellocl.c) */ /* Usage: hellocl host_name */ /* */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #define PROT_NO 5001 /* ポート番号 */ #define BUF_MAX 64 /* 通信バッファサイズ */ static struct sockaddr_in sv_addr; /* サーバアドレス */ static struct hostent *sv_ip; /* サーバIPアドレス */ static int sid; /* ソケット識別子 */ static char buf[BUF_MAX]; /* 通信バッファ */ /* クライアントメイン */ int main(argc, argv) int argc; char *argv[]; /* argv[1]:サーバホスト名 */ { int rtn; /* 返却値 */ /* コネクション型ソケットの作成 (socket) */ sid = socket(AF_INET, SOCK_STREAM, 0); if (sid < 0) { perror("cl:socket"); exit(1); } /* サーバのIPアドレスを取得 */ sv_ip = gethostbyname(argv[1]); if (sv_ip == NULL) { perror("cl:gethostbyname"); exit(1); } /* ソケットの接続要求 (connect) */ bzero((char *)&sv_addr, sizeof(sv_addr)); sv_addr.sin_family = AF_INET; sv_addr.sin_port = htons(PROT_NO); memcpy((char *)&sv_addr.sin_addr, (char *)sv_ip->h_addr, sv_ip->h_length); rtn = connect(sid, (struct sockaddr *)&sv_addr, sizeof(sv_addr)); if (rtn < 0) { perror("cl:connect"); close(sid); exit(1); } /* メッセージ通信処理 (send/recv) */ rtn = recv(sid, buf, BUF_MAX, 0); if (rtn < 0) perror("cl:recv"); printf("%s\n", buf); /* ソケットの開放 (shutdown/close) */ rtn = shutdown(sid, 2); if (rtn < 0) perror("cl:shutdown"); close(sid); exit(0); }
環境はUbuntu8.10 + gccです。
Fedoraでは無いですけど問題は無いはずです。
とりあえず、コンパイルオプションがいらないと思います。
コンパイラオプションを削除すればコンパイルは一応可能です。
警告出まくりですけど。
$ make cc -o hellosv hellosv.c hellosv.c: In function ‘main’: hellosv.c:45: 警告: incompatible implicit declaration of built-in function ‘bzero’ hellosv.c:48: 警告: incompatible implicit declaration of built-in function ‘memcpy’ hellosv.c:50: 警告: passing argument 2 of ‘bind’ from incompatible pointer type hellosv.c:66: 警告: passing argument 2 of ‘accept’ from incompatible pointer type hellosv.c:85: 警告: incompatible implicit declaration of built-in function ‘exit’ cc -o hellocl hellocl.c hellocl.c: In function ‘main’: hellocl.c:31: 警告: incompatible implicit declaration of built-in function ‘exit’ hellocl.c:38: 警告: incompatible implicit declaration of built-in function ‘exit’ hellocl.c:42: 警告: incompatible implicit declaration of built-in function ‘bzero’ hellocl.c:45: 警告: incompatible implicit declaration of built-in function ‘memcpy’ hellocl.c:47: 警告: passing argument 2 of ‘connect’ from incompatible pointer type hellocl.c:51: 警告: incompatible implicit declaration of built-in function ‘exit’ hellocl.c:63: 警告: incompatible implicit declaration of built-in function ‘exit’
Unixでのネットワークプログラミングを勉強するならば、個人的には「UNIXネットワークプログラミング」がおすすめ。
ISBN:4894712059:detail
あとは直接必要では無いけど、IPCとプロセス、スレッドもあればたいがいの事ができるはずです。
プロセス、スレッドは複数との同時通信とかに、IPCは他のプロセス、スレッド間でのデータのやりとりに使います。
zzz_1980さんも「UNIXネットワークプログラミング」をおすすめされていましたし良書そうなので、是非購入したいと思います。
基本部分をしっかり勉強してIPC、プロセス、スレッドといった次のステップに進んでいきたいですね。
コメントありがとうございました。