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

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

ただいまの
回答率

90.50%

  • C

    4541questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

recvシステムコールの引数であるデータの長さ

解決済

回答 2

投稿

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

cingyan

score 19

C言語によるプログラミング、応用編という本で分からないところがあり質問します。
wwwクライアントのプログラムです。

main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int parse_args(int argc,char *argv[],char **phostname,char **pfilepath);
int init_sockaddr_in(char *hostname,struct sockaddr_in *sin);
int client_process(int fd,char *hostname,char *filepath);
int send_request(int fd,char *hostname,char *filepath);
int recv_reply(int fd);

int main(int argc,char *argv[])
{
    char *phostname,*pfilepath;
    int fd,ret=EXIT_FAILURE;
    struct sockaddr_in sin;

    printf("引数の解析...\n");
    if(parse_args(argc,argv,&phostname,&pfilepath))
    {
        fprintf(stderr,"使用法: %s -h [hostname] -f [filepath]\n",
            argv[0]);
        exit(EXIT_FAILURE);
    }
    printf("ソケット生成...\n");
    if((fd=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
    {
        fprintf(stderr,"ソケット生成に失敗しました\n");
        exit(EXIT_FAILURE);
    }
    printf("アドレス構造体初期化...\n");
    if(init_sockaddr_in(phostname,&sin)<0)
    {
        fprintf(stderr,"アドレス構造体の初期化に失敗しました\n");
        goto close_socket;

    }
    printf("%sへ接続中...\n",inet_ntoa(sin.sin_addr));
    if(connect(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
    {
        fprintf(stderr,"サーバーへのに失敗しました\n");
        goto close_socket;
    }
    ret=client_process(fd,phostname,pfilepath);
close_socket:
    close(fd);
    return ret;
}


client_process.c

int send_request(int fd,char *hostname,char *filepath);
int recv_reply(int fd);

int client_process(int fd,char *hostname,char *filepath)
{
    printf("リクエスト送信中...\n");
    if(send_request(fd,hostname,filepath))
    {
        fprintf(stderr,"リクエスト送信に失敗しました\n");
        return -1;
    }
    printf("データ受信中...\n");
    if(recv_reply(fd))
    {
        fprintf(stderr,"受信に失敗しました\n");
        return -1;
    }
    printf("\n正常にデータを受信しました\n");
    return EXIT_SUCCESS;
}

recv_reply.c

int recv_reply(int fd)
{
    fd_set readfds;
    char buf[256];/*データ受信バッファ*/
    int length;

    while(1)
    {    /*ディスクリプタ集合の初期化*/
        FD_ZERO(&readfds);
        FD_SET(fd,&readfds);
        memset(buf,0,sizeof(buf));
        /*サーバーからのデータの到着を待つ*/
        if(select(fd+1,&readfds,NULL,NULL,NULL)<0)
        {
            fprintf(stderr,"selectに失敗しました");
            return -1;
        }
        /*ディスクリプタに受信したデータがある?*/
        if(FD_ISSET(fd,&readfds))
        {
            /*データを受信*//*ここが不明点*/
            length=recv(fd,buf,sizeof(buf-1),0);
            if(length<0)
                return -1;
            else if(length==0)    /*受信正常終了*/
                break;
            /*受信したデータを標準出力へ*/
            printf("%*s",length,buf);
        }
    }
    return EXIT_SUCCESS;
}

質問は、データを受信して標準出力に出す、recv_reply関数です。
その中の、
recv(fd,buf,sizeof(buf-1),0);で、
sizeof(buf-1)の
-1 は、どういう意味であるのかということです。

よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

buf の最後に\0を入れるためではないでしょうか?
recv()で文字列を受け取ったとき、その最後に\0がない場合、またはデータが255文字以上だったときにも\0で文字列が終わるようにmemset()で0を入れています。
-1がないと、bufの最後まで文字が入ってしまい、\0で終端されない状況を避けるためです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/09 12:10

    ご回答ありがとうございました。。
    \0を入れることで、正常に文字列として処理ができると言うことですね。

    キャンセル

0

バグですね。
おそらく、sizeof(buf)-1が頭の中にあったけど、指が違うように動いたということでしょう。

sizeof(buf-1)だと、sizeof(char*)と同じで普通は8
sizeof(buf)-1だと、100-199です。

-1する理由としては、nob.さんの回答の通り。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/09 12:13

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

    >sizeof(buf)-1だと、100-1で99です。
    100はどこから出てきたのか、教えてください。

    printf("sizefo (buf)-1=%zu\n",sizeof(buf)-1);をすると、
    sizefo (buf)-1=255
    と出てきたのですが、何が間違っているのか教えてください。

    キャンセル

  • 2017/10/09 19:10

    >100はどこから出てきたのか、教えてください。
    すいません。256の書き誤りです。
    私が、char buf[100]; することが多いので、つい書いてしまいました。

    キャンセル

  • 2017/10/10 12:15

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

    キャンセル

同じタグがついた質問を見る

  • C

    4541questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。