現在、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

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

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2009/06/16 20:52:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:zzz_1980 No.5

回答回数492ベストアンサー獲得回数64

ポイント27pt

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

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);
}

id:schlussel

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));
2009/06/16 20:47:10

その他の回答4件)

id:longicorn No.1

回答回数56ベストアンサー獲得回数6

ポイント19pt

環境は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’
id:schlussel

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

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"です。

2009/06/15 23:45:11
id:pahoo No.2

回答回数5960ベストアンサー獲得回数633

ポイント9pt

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

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

id:schlussel

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

"/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"を実行し、再コンパイル

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

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

2009/06/16 00:40:13
id:kenichiice No.3

回答回数49ベストアンサー獲得回数7

ポイント27pt

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

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

hellosv localhost
hellocl localhost

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

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

id:schlussel

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

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

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

2009/06/16 19:53:52
id:longicorn No.4

回答回数56ベストアンサー獲得回数6

ポイント18pt

>"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) 
id:schlussel

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

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

2009/06/16 19:55:20
id:zzz_1980 No.5

回答回数492ベストアンサー獲得回数64ここでベストアンサー

ポイント27pt

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

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);
}

id:schlussel

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));
2009/06/16 20:47:10
  • id:longicorn
    ちょっと書き忘れていたので。


    Unixでのネットワークプログラミングを勉強するならば、個人的には「UNIXネットワークプログラミング」がおすすめ。
    ISBN:4894712059:detail

    あとは直接必要では無いけど、IPCとプロセス、スレッドもあればたいがいの事ができるはずです。
    プロセス、スレッドは複数との同時通信とかに、IPCは他のプロセス、スレッド間でのデータのやりとりに使います。
  • id:schlussel
    >longicornさん
    zzz_1980さんも「UNIXネットワークプログラミング」をおすすめされていましたし良書そうなので、是非購入したいと思います。

    基本部分をしっかり勉強してIPC、プロセス、スレッドといった次のステップに進んでいきたいですね。

    コメントありがとうございました。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません