人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

現在、Fedora 11でソケットプログラミングの学習を行っています。

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

解決方法をご教示いただけないでしょうか?

●質問者: schlussel
●カテゴリ:コンピュータ 学習・教育
✍キーワード:accept ALL BIND CC const
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● longicorn
●19ポイント

環境は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’
◎質問者からの返答

ご回答ありがとうございます。

makefileのコンパイルオプションを削除して"make all"を実行したところコンパイルは通り

"hellosv"と"hellocl"が生成されましたが、これらを実行すると「セグメンテーション違反です」

と表示されてしまい、実行することができません。

http://www.asahi-net.or.jp/~vs6k-nkym/pong_compile.html

こちらのWebサイトで解説されているように、socketライブラリーとnslライブラリーを利用するため

コンパイルオプションの"-lsocket"と"-lnsl"は必要な気がするのですが…。

※利用しているコンパイラのバージョンを書き忘れていました。

利用しているバージョンは"gcc version 4.4.0"です。


2 ● pahoo
●9ポイント

socketがライブラリの検索パスに登録されていないようです。

ldconfigを実行してみてください。⇒(参考)共有ライブラリをシステムに認識させるには

◎質問者からの返答

ご回答ありがとうございます。

"/usr/bin/ld: cannot find -lsocket"というエラーメッセージが表示されていたので

なんとなく、socketがライブラリの検索パスに登録されていないのではないかと感じて

はいたのですが、こうすれば共有ライブラリをシステムに認識させることができるんですね。

大変勉強になりました。

さっそく、"/etc/ld.so.conf"に"/usr/local/lib"を追加後、"/sbin/ldconfig"を実行し、再コンパイル

を行いましたが、残念ながらエラー内容は変わりませんでした。その後、"/etc/ld.so.conf"に追加するのは"socket.h"のある

"/usr/include/sys"なのではないかと思い、再編集後、"/sbin/ldconfig"を実行し、再コンパイル

を行いましたが、やはりエラー内容は変わりませんでした。

とはいえ、なんとなく解決の糸口は見つかったような気がしてきました。


3 ● kenichiice
●27ポイント

「"hellosv"と"hellocl"が生成」されたのでしたら、コンパイルはできているので ldconfig などの実行は必要ないと思います。

このプログラムは起動時に引数を指定しないとセグメンテーション違反になると思いますが、実行する際に引数は指定されたでしょうか。

hellosv localhost
hellocl localhost

のようにホスト名を引数に指定すれば動くのではないでしょうか。

引数が指定されなくても動くようにプログラムの方も修正すべきだとは思いますが。

◎質問者からの返答

恥ずかしながら、まさにその通りでした。

おかげさまで、プログラムの中身を見てどのような引数が起動時に必要か分かるようになりました。

ありがとうございました。


4 ● longicorn
●18ポイント

>"hellosv"と"hellocl"が生成されましたが、これらを実行すると「セグメンテーション違反です」

>と表示されてしまい、実行することができません。


取り合えずコンパイル時に警告は出てあたりまえ。「セグメンテーション違反です」で落ちるのも当たり前。

答えをそのまま書くのでは勉強にならないのでヒントだけ。


警告のヒント

1:必要なヘッダが無い。

2:connect(2)の第2引数の型が違う。


セグって落ちるヒント

sv_ip = gethostbyname(argv[1]);

>※利用しているコンパイラのバージョンを書き忘れていました。

> 利用しているバージョンは"gcc version 4.4.0"です。

そういえばこちらも書いていませんでしたね。

まああまり関係ないとは思うけど念のためこちらの環境を書いておきます。

Ubuntuでaptで入れただけです。

$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
コンフィグオプション: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
スレッドモデル: posix
gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12) 
◎質問者からの返答

試行錯誤の末、なんとか起動できるようになりました。

ありがとうございました。


5 ● zzz_1980
●27ポイント ベストアンサー

本気で勉強するなら、以下を薦めておきます。

UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI

UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI

  • 作者: W.リチャード スティーヴンス
  • 出版社/メーカー: ピアソンエデュケーション
  • メディア: 単行本

とりあえず修正してみました。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);
}

◎質問者からの返答

Webページに掲載されているソースコードと修正していただいたソースコードを見比べながら

どのように書けば警告が出なくなるのか試すことができ、非常に勉強になりました。

ありがとうございました。

※今後参照される方が分かりやすいように変更箇所を簡単にメモしておきます。

/* */
/* コネクション型のサーバプログラム (hellosv.c) */
/* */
//add
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

//fix
/* ソケットに名前を付加 (bind) */
rtn = bind(sid1, (struct sockaddr *)&sv_addr, sizeof(sv_addr));
/* クライアントからの接続要求の受信 (accept) */
sid2 = accept(sid1, (struct sockaddr *)&cl_addr, (socklen_t *)&cl_size);
/* */
/* コネクション型クライアントプログラム (hellocl.c) */
/* */
//add
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

//fix
/* ソケットの接続要求 (connect) */
rtn = connect(sid, (struct sockaddr *)&sv_addr, sizeof(sv_addr));
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ