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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

Q&A

解決済

2回答

1378閲覧

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

cingyan

総合スコア29

C

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

1グッド

1クリップ

投稿2017/10/08 05: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 は、どういう意味であるのかということです。

よろしくお願いします。

jjs👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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

投稿2017/10/08 05:31

nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2017/10/09 03:10

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

0

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

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

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

投稿2017/10/08 11:38

otn

総合スコア84538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cingyan

2017/10/09 03:13

ご回答、ありがとうございました。。 >sizeof(buf)-1だと、100-1で99です。 100はどこから出てきたのか、教えてください。 printf("sizefo (buf)-1=%zu\n",sizeof(buf)-1);をすると、 sizefo (buf)-1=255 と出てきたのですが、何が間違っているのか教えてください。
otn

2017/10/09 10:10

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

2017/10/10 03:15

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問