質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.23%

ソケット通信のシミュレーションに出てきたdatagram errorの治し方を知りたいです

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 331

SioRyu

score 11

大学の授業で習っている最中なのですが、通信システムのシミュレーションをしたいプログラムで。出された課題内容がプログラムの機能を拡張するもので。一つ目の課題は特に問題なくクリアしたのですが二つ目でエラーが出てしまいどう解決すればいいかわからず、皆様に直し方をお聞きしたいです。
二つ目の課題では
人名1,人名2
の複数の入力がされた場合それぞれの人名の携帯番号を返すようにプログラムを拡張するものでした。
5つポインター関係のエラーが出ていたのですが、そちらは何とかいろいろ調べながら自力でエラーを消したのですが、もしかしたらポインターをいじりすぎたのではないかと思っております。

問題が出ているのはサーバー側の

/* 検索したデータをソケットに書き込む */
        datalen = strlen(*data[i]);
        if(sendto(socd, data, datalen, 0, (struct sockaddr *)&c_address, c_addrlen) != datalen) {
            fprintf(stderr, "datagram error\n"); 
            exit(1);
        }


この部分です

動作環境は大学のパソコンで
仮想マシンCentOS Linux socket通信環境

  1. サーバー側
/* コネクションレスの簡単なデータ検索サーバ(dg_server.c) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル      */
#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル  */
#include <netdb.h>      /* gethostbyname()を用いるためのヘッダファイル */
#include <errno.h>
#include <string.h>
#define  MAXHOSTNAME    64
#define  S_UDP_PORT    (u_short)5000  /* 本サーバが用いるポート番号 */
#define  MAXKEYLEN    128
#define  MAXDATALEN    256
int setup_dgserver(struct hostent*, u_short);
void db_search(int);

main()
{
    int    socd;
    char    s_hostname[MAXHOSTNAME];
    struct hostent    *s_hostent;

    /* サーバのホスト名とそのInternetアドレス(をメンバに持つhostent構造体)を求める */
    gethostname(s_hostname, sizeof(s_hostname));
    s_hostent = gethostbyname(s_hostname);

    /* データグラムサーバの初期設定 */
    socd = setup_dgserver(s_hostent, S_UDP_PORT);

    /* クライアントからのデータ検索要求の処理 */
    db_search(socd);
}

int setup_dgserver(struct hostent *hostent, u_short port)
{
    int    socd;
    struct sockaddr_in    s_address;

    /* インターネットドメインのSOCK_DGRAM(UDP)型ソケットの構築 */
    if((socd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket");exit(1); }

    /* アドレス(Internetアドレスとポート番号)の作成 */
    bzero((char *)&s_address, sizeof(s_address));
    s_address.sin_family = AF_INET;
    s_address.sin_port = htons(port);
    bcopy((char *)hostent->h_addr, (char *)&s_address.sin_addr, hostent->h_length);

    /* アドレスのソケットへの割り当て */
    if(bind(socd, (struct sockaddr *)&s_address, sizeof(s_address)) < 0) { perror("bind");exit(1); }

    return socd;
}

void db_search(int socd) /* クライアントがデータ検索要求を処理する */
{
    struct sockaddr_in    c_address;
    int    c_addrlen;
    char    key[MAXKEYLEN+1], data[5][MAXDATALEN+1];
    int    keylen, datalen;
    static char *db[] = {"amano-taro","0426-91-9418","ishida-jiro","0426-91-9872",
                             "ueda-saburo","0426-91-9265","ema-shiro","0426-91-7254",
                             "ooishi-goro","0426-91-9618",NULL};
    int i=0;
    char token;
    char    **dbp;

    while(1) {
        /* キーをソケットから読み込む */
        c_addrlen = sizeof(c_address);
        if((keylen = recvfrom(socd, key, MAXKEYLEN, 0, (struct sockaddr *)&c_address, &c_addrlen)) < 0) {
            perror("recvfrom");
            exit(1);
        }
        key[keylen] = '\0';
        printf("Received key> %s\n",key);
        /* キーを用いてデータ検索 */
        token = *strtok(key, ",");
        do{
          dbp = db;
          while(*dbp) {
              if(strcmp(&token, *dbp) == 0) {
                  strcpy(data[i], *(++dbp));
                  break;
              }
              dbp += 2;
          }
          i++;
        }while(token == *strtok(NULL,","));
        if(*dbp == NULL) strcpy(*data, "No entry");

        /* 検索したデータをソケットに書き込む */
        datalen = strlen(*data[i]);
        if(sendto(socd, data, datalen, 0, (struct sockaddr *)&c_address, c_addrlen) != datalen) {
            fprintf(stderr, "datagram error\n"); 
            exit(1);
        }
        for(i=0;i<5;i++){
          printf("Sent data> %s\n", data[i]);
        }
    }
}
  1. クライアント側
/* コネクションレスの簡単なデータ検索クライアント(dg_client.c) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル      */
#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル  */
#include <netdb.h>      /* gethostbyname()を用いるためのヘッダファイル */
#include <errno.h>
#include <string.h>
#define  MAXHOSTNAME    64
#define     S_UDP_PORT    (u_short)5000 
#define  MAXKEYLEN    128
#define     MAXDATALEN    256  
int setup_dgclient(struct hostent*, u_short, struct sockaddr_in*, int*);
void remote_dbsearch(int, struct sockaddr_in*, int);

main()
{
    int    socd;
    char    s_hostname[MAXHOSTNAME];
    struct hostent    *s_hostent;
    struct sockaddr_in s_address;
    int    s_addrlen;

    /* サーバのホスト名の入力 */
    printf("server host name?: "); scanf("%s",s_hostname);
    /* サーバホストのInternetアドレス(をメンバに持つhostent構造体)を求める */
    if((s_hostent = gethostbyname(s_hostname)) == NULL) {
        fprintf(stderr, "server host does not exists\n");
        exit(1);
    }

    /* データグラムクライアントの初期設定 */
    socd = setup_dgclient(s_hostent, S_UDP_PORT, &s_address, &s_addrlen);

    /* リモートデータベース検索 */
    remote_dbsearch(socd, &s_address, s_addrlen);

    close(socd);
    exit(0);
}

int setup_dgclient(struct hostent *hostent, u_short port, struct sockaddr_in *s_addressp, int *s_addrlenp)
{
        int     socd;
        struct sockaddr_in      c_address;

    /* インターネットドメインのSOCK_DGRAM(UDP)型ソケットの構築 */
        if((socd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket");exit(1); }

    /* サーバのアドレス(Internetアドレスとポート番p));
        s_addressp->sin_family = AF_INET;
        s_addressp->sin_port = htons(port);
        bcopy((char *)hostent->h_addr, (char *)&s_addressp->sin_addr, hostent->h_length);
    *s_addrlenp = sizeof(*s_addressp);

    /* クライアントのアドレス(Internetアドレスとポート番号)の作成 */
        bzero((char *)&c_address, sizeof(c_address));
        c_address.sin_family = AF_INET;
        c_address.sin_port = htons(0);               /* ポート番号の自動割り当て */
    c_address.sin_addr.s_addr = htonl(INADDR_ANY); /* Internetアドレスの自動割り当て */

    /* クライアントアドレスのソケットへの割り当て */
    if(bind(socd, (struct sockaddr *)&c_address, sizeof(c_address)) < 0) { perror("bind");exit(1); }

    return socd;
}

void remote_dbsearch(int socd, struct sockaddr_in *s_addressp, int s_addrlen) /* サーバにキーを送り検索結果(データ)を受け取る */
{
    char    key[MAXKEYLEN+1], data[MAXDATALEN+1];
    int    keylen, datalen;
    while(1){
    /* キーを標準入力から入力 */
    printf("key?: ");
    if(scanf("%s",key)==EOF)break;
    /* キーをソケットに書き込む */
    keylen = strlen(key);

    if(sendto(socd, key, keylen, 0, (struct sockaddr *)s_addressp, s_addrlen) != keylen) {
        fprintf(stderr, "datagram error\n");
        exit(1);
    }
    /* 検索データをソケットから読み込む */
    if((datalen = recvfrom(socd, data, MAXDATALEN, 0, NULL, &s_addrlen)) < 0) { 
        perror("recvfrom");
        exit(1);
    }
    /* データを標準出力に出力 */
    data[datalen] = '\0';
    fputs("data: ",stdout);puts(data);

    }
}

実行結果:
[root@skt52 Linux_share]# gcc -o dg_client dg_client.c
[root@skt52 Linux_share]# ./dg_client
server host name?: skt52
key?: amano-taro
datagram error

[root@skt52 Linux_share]# gcc -o dg_server dg_server.c
[root@skt52 Linux_share]# ./dg_server

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

複数の人名が入力された場合、その電話番号を返すように修正しました。client側の修正は必要ありません。
サーバー側です。

/* コネクションレスの簡単なデータ検索サーバ(dg_server.c) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル      */
#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル  */
#include <netdb.h>      /* gethostbyname()を用いるためのヘッダファイル */
#include <errno.h>
#include <string.h>
#define  MAXHOSTNAME    64
#define  S_UDP_PORT    (u_short)5000  /* 本サーバが用いるポート番号 */
#define  MAXKEYLEN    128
#define  MAXDATALEN    256
#define  MAXKEYCOUNT   5                //ADD
int setup_dgserver(struct hostent*, u_short);
void db_search(int);

main()
{
    int    socd;
    char    s_hostname[MAXHOSTNAME];
    struct hostent    *s_hostent;

    /* サーバのホスト名とそのInternetアドレス(をメンバに持つhostent構造体)を求める */
    gethostname(s_hostname, sizeof(s_hostname));
    s_hostent = gethostbyname(s_hostname);

    /* データグラムサーバの初期設定 */
    socd = setup_dgserver(s_hostent, S_UDP_PORT);

    /* クライアントからのデータ検索要求の処理 */
    db_search(socd);
}

int setup_dgserver(struct hostent *hostent, u_short port)
{
    int    socd;
    struct sockaddr_in    s_address;

    /* インターネットドメインのSOCK_DGRAM(UDP)型ソケットの構築 */
    if((socd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket");exit(1); }

    /* アドレス(Internetアドレスとポート番号)の作成 */
    bzero((char *)&s_address, sizeof(s_address));
    s_address.sin_family = AF_INET;
    s_address.sin_port = htons(port);
    bcopy((char *)hostent->h_addr, (char *)&s_address.sin_addr, hostent->h_length);

    /* アドレスのソケットへの割り当て */
    if(bind(socd, (struct sockaddr *)&s_address, sizeof(s_address)) < 0) { perror("bind");exit(1); }

    return socd;
}
//ADD開始
//文字列strをカンマで分割し、keyaddrの配列へそのアドレスを返す(MAXKEYCOUNTまでしか処理しない)
void get_keys(char *str,char *keyaddr[MAXKEYCOUNT],int *key_count)
{
    int     ix = 0;
    keyaddr[ix] = str;
    while(*str != 0x00){
        if (*str == ','){
            *str = 0x00;
            if (ix + 1 == MAXKEYCOUNT) break;
            keyaddr[ix+1] = str + 1;
            ix++;
        }
        str++;
    }
    *key_count = ix + 1;
}
//db内の名前をstrで検索し、電話番号へのポインターを返す。NotFound時はNULLを返す。
char *find_name(char *str,char **db)
{
    int i = 0;
    while(1){
        if (db[i] == NULL) break;
        if (strcmp(db[i],str)==0) return db[i+1];
        i += 2;
    }
    return NULL;
}
//ADD終了
void db_search(int socd) /* クライアントがデータ検索要求を処理する */
{
    struct sockaddr_in    c_address;
    int    c_addrlen;
    char    key[MAXKEYLEN+1], data[(MAXDATALEN+1)*MAXKEYCOUNT+1];   //MOD
    char    *keyaddr[MAXKEYCOUNT];
    int    keylen, datalen;
    static char *db[] = {"amano-taro","0426-91-9418","ishida-jiro","0426-91-9872",
                             "ueda-saburo","0426-91-9265","ema-shiro","0426-91-7254",
                             "ooishi-goro","0426-91-9618",NULL};
    int i=0;
    char token;
    char    *dbp;   //MOD
    int     key_count;  //ADD

    while(1) {
        /* キーをソケットから読み込む */
        c_addrlen = sizeof(c_address);
        if((keylen = recvfrom(socd, key, MAXKEYLEN, 0, (struct sockaddr *)&c_address, &c_addrlen)) < 0) {
            perror("recvfrom");
            exit(1);
        }
        key[keylen] = '\0';
        printf("Received key> %s\n",key);
        //全面改訂開始
        /* キーを,で分割*/
        get_keys(key,keyaddr,&key_count);
        /* キーを用いてデータ検索 */
        strcpy(data,"");
        for (i= 0; i < key_count; i++){
            printf("%d<%s>\n",i,keyaddr[i]);
            dbp = find_name(keyaddr[i],db);
            if (i != 0) strcat(data,"\n");
            if (dbp == NULL){
                strcat(data,"No entry");
            }else{
                strcat(data,dbp);
            }
        }
        /* 検索したデータをソケットに書き込む */
        datalen = strlen(data);
        if(sendto(socd, data, datalen, 0, (struct sockaddr *)&c_address, sizeof(c_address)) != datalen) {
            fprintf(stderr, "datagram error:%d\n",errno);
            exit(1);
        }
        printf("Sent data> %s\n", data);
        //全面改訂終了
    }
}


尚、処理するのは5人(MAXKEYCOUNT)迄とし、それを超えた場合は、打ち切っています。
まず、人名へのポインターを
keyaddr[0]・・・1人目の名前へのポインター
keyaddr[1]・・・2人目の名前へのポインター、以降同様
のように作成し、
その名前で、dbを検索し、あれば、その電話番号をセット、なければ、No entryをdataへセットして行きます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

datalen = strlen(*data[i]);

datalen = strlen(data);
じゃない?


datalen = strlen(data[i]);
if(sendto(socd, data[i], datalen, 0, (struct sockaddr *)&c_address, c_addrlen) != datalen) {

こっちのほうか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/05 01:53

    ありがとうございます、さっそく明日試してみたいと思います。

    キャンセル

  • 2018/10/10 18:35

    書いていただいたとおりに直した上で試してみたのですが、やはり
    [root@skt60 Linux_share]# gcc -o dg_client dg_client.c
    [root@skt60 Linux_share]# ./dg_client
    server host name?: skt60
    key?: amano-taro
    datagram error
    こんな感じでして、どこがだめでdatagram errorに落ちるのかわかりません。自分が浅い知識でいろいろといじってしまった上の部分に原因があるのかもしれません。
    エラーで
    dg_server.c:92: 警告: passing argument 1 of ‘strlen’ makes pointer from integer without a cast
    /usr/include/string.h:399: note: expected ‘const char *’ but argument is of type ‘char’
    このように出ていた部分をに*やら&やらをつけたり消したり、いろいろ試しながら消していったので、もしかしたらこのせいかと。
    よろしければどこか自分の間違えを見つけていただけると助かります。

    キャンセル

  • 2018/10/10 18:43

    そのsendto関数の戻り値が何を返しているのかを調べてみればどうでしょう

    動かない、なぜ?ということで思考停止するんではなくて、コードを単純化して、何がまずいのかを探っていくようにしましょう
    また、EclipseのようなC言語のデバッグができる統合環境を入れてはどうでしょうか。
    任意の行で止めて、変数のナカミを参照することができます

    キャンセル

0

とりあえず、修正しておきました。
サーバー側

/* コネクションレスの簡単なデータ検索サーバ(dg_server.c) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル      */
#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル  */
#include <netdb.h>      /* gethostbyname()を用いるためのヘッダファイル */
#include <errno.h>
#include <string.h>
#define  MAXHOSTNAME    64
#define  S_UDP_PORT    (u_short)5000  /* 本サーバが用いるポート番号 */
#define  MAXKEYLEN    128
#define  MAXDATALEN    256
int setup_dgserver(struct hostent*, u_short);
void db_search(int);

main()
{
    int    socd;
    char    s_hostname[MAXHOSTNAME];
    struct hostent    *s_hostent;

    /* サーバのホスト名とそのInternetアドレス(をメンバに持つhostent構造体)を求める */
    gethostname(s_hostname, sizeof(s_hostname));
    s_hostent = gethostbyname(s_hostname);

    /* データグラムサーバの初期設定 */
    socd = setup_dgserver(s_hostent, S_UDP_PORT);

    /* クライアントからのデータ検索要求の処理 */
    db_search(socd);
}

int setup_dgserver(struct hostent *hostent, u_short port)
{
    int    socd;
    struct sockaddr_in    s_address;

    /* インターネットドメインのSOCK_DGRAM(UDP)型ソケットの構築 */
    if((socd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket");exit(1); }

    /* アドレス(Internetアドレスとポート番号)の作成 */
    bzero((char *)&s_address, sizeof(s_address));
    s_address.sin_family = AF_INET;
    s_address.sin_port = htons(port);
    bcopy((char *)hostent->h_addr, (char *)&s_address.sin_addr, hostent->h_length);

    /* アドレスのソケットへの割り当て */
    if(bind(socd, (struct sockaddr *)&s_address, sizeof(s_address)) < 0) { perror("bind");exit(1); }

    return socd;
}

void db_search(int socd) /* クライアントがデータ検索要求を処理する */
{
    struct sockaddr_in    c_address;
    int    c_addrlen;
    char    key[MAXKEYLEN+1], data[MAXDATALEN+1];   //MOD
    int    keylen, datalen;
    static char *db[] = {"amano-taro","0426-91-9418","ishida-jiro","0426-91-9872",
                             "ueda-saburo","0426-91-9265","ema-shiro","0426-91-7254",
                             "ooishi-goro","0426-91-9618",NULL};
    int i=0;
    char token;
    char    *dbp;   //MOD

    while(1) {
        /* キーをソケットから読み込む */
        c_addrlen = sizeof(c_address);
        if((keylen = recvfrom(socd, key, MAXKEYLEN, 0, (struct sockaddr *)&c_address, &c_addrlen)) < 0) {
            perror("recvfrom");
            exit(1);
        }
        key[keylen] = '\0';
        printf("Received key> %s\n",key);
        /* キーを用いてデータ検索 */
        //全面改訂開始
        i = 0;
        dbp = NULL;
        while(1){
            if (db[i] == NULL) break;
            if (strcmp(db[i],key) == 0){    //名前が一致なら
                dbp = db[i+1];              //電話番号をセット
                break;
            }
            i += 2;
        }
        if(dbp == NULL){
            strcpy(data, "No entry");
        }else{
            strcpy(data,dbp);
        }
        /* 検索したデータをソケットに書き込む */
        datalen = strlen(data);
        if(sendto(socd, data, datalen, 0, (struct sockaddr *)&c_address, sizeof(c_address)) != datalen) {
            fprintf(stderr, "datagram error:%d\n",errno);
            exit(1);
        }
        printf("Sent data> %s\n", data);
        //全面改訂終了
    }
}


次がクライアント側

/* コネクションレスの簡単なデータ検索クライアント(dg_client.c) */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> /* ソケットのための基本的なヘッダファイル      */
#include <netinet/in.h> /* インタネットドメインのためのヘッダファイル  */
#include <netdb.h>      /* gethostbyname()を用いるためのヘッダファイル */
#include <errno.h>
#include <string.h>
#define  MAXHOSTNAME    64
#define     S_UDP_PORT    (u_short)5000
#define  MAXKEYLEN    128
#define     MAXDATALEN    256
int setup_dgclient(struct hostent*, u_short, struct sockaddr_in*, int*);
void remote_dbsearch(int, struct sockaddr_in*, int);

main()
{
    int    socd;
    char    s_hostname[MAXHOSTNAME];
    struct hostent    *s_hostent;
    struct sockaddr_in s_address;
    int    s_addrlen;
    int     i;
    /* サーバのホスト名の入力 */
    printf("server host name?: "); scanf("%s",s_hostname);
    /* サーバホストのInternetアドレス(をメンバに持つhostent構造体)を求める */
    if((s_hostent = gethostbyname(s_hostname)) == NULL) {
        fprintf(stderr, "server host does not exists\n");
        exit(1);
    }
    /* データグラムクライアントの初期設定 */
    socd = setup_dgclient(s_hostent, S_UDP_PORT, &s_address, &s_addrlen);

    /* リモートデータベース検索 */
    remote_dbsearch(socd, &s_address, s_addrlen);

    close(socd);
    exit(0);
}

int setup_dgclient(struct hostent *hostent, u_short port, struct sockaddr_in *s_addressp, int *s_addrlenp)
{
        int     socd;
        struct sockaddr_in      c_address;

    /* インターネットドメインのSOCK_DGRAM(UDP)型ソケットの構築 */
        if((socd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("socket");exit(1); }

    /* サーバのアドレス(Internetアドレスとポート番p));
        s_addressp->sin_family = AF_INET;
        s_addressp->sin_port = htons(port);
        bcopy((char *)hostent->h_addr, (char *)&s_addressp->sin_addr, hostent->h_length);
    *s_addrlenp = sizeof(*s_addressp);

    /* クライアントのアドレス(Internetアドレスとポート番号)の作成 */
        bzero((char *)&c_address, sizeof(c_address));
        c_address.sin_family = AF_INET;
        //c_address.sin_port = htons(0);               /* ポート番号の自動割り当て */
        c_address.sin_port = htons(port);               /* ポート番号の自動割り当て */  //MOD
        //c_address.sin_addr.s_addr = htonl(INADDR_ANY); /* Internetアドレスの自動割り当て */
        bcopy((char*)hostent->h_addr,(char*)&c_address.sin_addr.s_addr,hostent->h_length);   //MOD
        *s_addressp = c_address;                                        //ADD
    /* クライアントアドレスのソケットへの割り当て */
    //if(bind(socd, (struct sockaddr *)&c_address, sizeof(c_address)) < 0) { perror("bind");exit(1); }  //DEL

    return socd;
}

void remote_dbsearch(int socd, struct sockaddr_in *s_addressp, int s_addrlen) /* サーバにキーを送り検索結果(データ)を受け取る */
{
    char    key[MAXKEYLEN+1], data[MAXDATALEN+1];
    int    keylen, datalen;
    while(1){
    /* キーを標準入力から入力 */
    printf("key?: ");
    if(scanf("%s",key)==EOF)break;
    /* キーをソケットに書き込む */
    keylen = strlen(key);

    //if(sendto(socd, key, keylen, 0, (struct sockaddr *)s_addressp, s_addrlen) != keylen) {
    if(sendto(socd, key, keylen, 0, (struct sockaddr *)s_addressp, sizeof(struct sockaddr_in)) != keylen) { //MOD
        fprintf(stderr, "datagram error:%d\n",errno);   //MOD
        exit(1);
    }
    /* 検索データをソケットから読み込む */
    //if((datalen = recvfrom(socd, data, MAXDATALEN, 0, NULL, &s_addrlen)) < 0) {
    if((datalen = recvfrom(socd, data, MAXDATALEN, 0, NULL, 0)) < 0) {  //MOD
        perror("recvfrom");
        exit(1);
    }
    /* データを標準出力に出力 */
    data[datalen] = '\0';
    fputs("data: ",stdout);puts(data);

    }
}


不明点は質問してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/10 18:20

    今回の条件で
    人名1,人名2
    の複数の入力がされた場合それぞれの人名の携帯番号を返すようにプログラムを拡張するもので
    このプログラムの場合
    入力:amano-taro,ishida-jiro
    出力:0426-91-9418
       0426-91-9872
    のように二つ出る必要がありまして、そのために二つの名前を区切る","が必要不可欠でして、dataが配列になっているのは複数ためて、一度にクライアントに書き出すのが目的です。自分の説明不足のようで、すみません。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる