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

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

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

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Q&A

解決済

1回答

7181閲覧

sendしてもrecvで止まったままになる

BitMaPT

総合スコア25

C

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

0グッド

0クリップ

投稿2017/12/23 15:18

編集2017/12/23 15:21

#問題
現在、C言語でソケット通信のプログラムを作成しています。

  • クライアントはsend()でrecv()で待機しているサーバー側にメッセージを送る。
  • メッセージを受け取ったサーバーはrecv()の停止状態から抜け出して受け取ったメッセージに基づいた処理を行う

上のような処理を目指しているのですがクライアント側がメッセージを送った後もrecv()で待機しているようで,処理が続行されません。
クライアント側のプログラムをctrl+Cで強制終了させると、ソケットが閉じられた(?)ためにサーバー側がrecv()を抜けて後ろに続く処理を実行します。
一度クライアント側でソケットのディスクリプタをclose()で閉じるしかないのでしょうか?

#コード

問題が発生している部分のコードです。拙いコードで見にくいかと思われますが、ご容赦ください。

####クライアント側

C

1 if((sockfd = Connect(hostname, port)) < 0) { 2 return; 3 } 4 5 printf("Write Command > "); 6 fflush(stdout); 7 8 if(fgets(cmd, MAX_CMD_LENGTH, stdin) == NULL) { 9 return; 10 } 11 12 size = send(sockfd, cmd, sizeof(cmd), 0); 13 if(size < 0) { 14 printf("SendCommand Send Error: %s\n", strerror(errno)); 15 return; 16 } 17 printf("send\n"); 18 recvdata.max = MAX_BUF_LENGTH; 19 recvdata.size = 0; 20 recvdata.data = (char*)malloc(sizeof(char) * recvdata.max); 21 22 while(1) { 23 size = recv(sockfd, buf, sizeof(buf), 0); 24 if(size == 0) break; 25 if(size < 0) { 26 printf("Error %d: %s\n", __LINE__, strerror(errno)); 27 return; 28 } 29 30 if(recvdata.max <= recvdata.size + size) { 31 recvdata.max *= 2; 32 recvdata.data = (char*)realloc(recvdata.data, sizeof(char) * recvdata.max); 33 if(recvdata.data == NULL) { 34 printf("memory error line:%d", __LINE__); 35 return; 36 } 37 } 38 39 memcpy(recvdata.data + recvdata.size, buf, size); 40 recvdata.size += size; 41 }

####サーバー側

C

1 while(1) { 2 clientSockfd = accept(serverSockfd, (struct sockaddr*)&sa, &saSize); 3 if(clientSockfd < 0) { 4 printf("(%s)Error line:%d %s\n", __FILE__, __LINE__, strerror(errno)); 5 close(serverSockfd); 6 return; 7 } 8 9 printf("accept\n"); fflush(stdout); 10 size = recv(clientSockfd, cmd, sizeof(cmd), 0); 11 if(size == 0) continue; 12 if(size < 0) { 13 printf("(%s)Error line:%d %s\n", __FILE__, __LINE__, strerror(errno)); 14 close(serverSockfd); 15 close(clientSockfd); 16 return; 17 } 18 19 printf("recive\n"); fflush(stdout); 20 ExchCharInStr('\n', '\0', cmd); 21 styledCmd = StyleCmd(cmd); 22 splitCmds = SplitStrByChar(' ', styledCmd, &cmdCount); 23 if(splitCmds[0][0] == '\0') { 24 close(clientSockfd); 25 continue; 26 } 27 28 free(styledCmd); 29 ExecuteCommand(splitCmds, cmdCount, clientSockfd); 30 31 close(clientSockfd); 32 }

#環境

VMware WorkStation 14 Player
Ubuntu 16.04LTS 64bit
gcc ver5.4.0

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

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

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

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

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

guest

回答1

0

自己解決

解決しました。単純なミスでした。
公開したプログラム外で一度connectしており、サーバー側のlistenでbacklogを0にしていなかったためにそのままプログラム内の2回目のconnectも保留状態として受け取っていたのでした。
サーバーは1回目のconnectにより確立ソケットからのsendに対して待機していたので2回目のconnectで確立したソケットのsendは保留していたようです。ctrl+Cでメッセージが受け取られるのも、1回目のconnectが切れて、2回目のconnectがループの初めでacceptされてそのまま実行されたようです。

投稿2017/12/24 09:03

BitMaPT

総合スコア25

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問