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

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

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

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

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

Q&A

解決済

1回答

973閲覧

ソケットプログラミングの文字列判断

muscle

総合スコア15

C

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

ソケット

TCP/IPにおいて、IPアドレスとサブアドレスであるポート番号を組み合わせたネットワークアドレスのことを呼びます。また、ソフトウェアアプリケーションにおいて、TCP/IP通信を行う為の仮想的なインターフェースという意味もある。

0グッド

0クリップ

投稿2022/03/10 07:49

ソケットで配列に入れた文字を判断し、同じならそれに対応した文字列を返すプログラムを作っています
エラーは起きてないのですが、文字が表示されません

有識者の方々、是非ともよろしくお願いいたします。

c言語

1#include <stdio.h> /* printf()、fprintf()に必要 */ 2#include <sys/socket.h> /* recv()、send()に必要 */ 3#include <unistd.h> /* close()に必要 */ 4#include <string.h> 5#define N 11 // 読み込み行数の上限値 6#define RCVBUFSIZE 32 /* 受信バッファのサイズ */ 7 8void DieWithError(char *errorMessage); /* エラー処理関数 */ 9 10void HandleTCPClient(int clntSocket) 11{ 12 char echoBuffer[RCVBUFSIZE]; /* エコー文字列のバッファ */ 13 int recvMsgSize; /* 受信メッセージのサイズ */ 14 /* クライアントからの受信メッセージ */ 15 if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) 16 DieWithError("recv() failed"); 17char qes[]= "年齢" ; 18char qes1[]= "性別" ; 19 20char ans[]= "19"; 21char ans1[]= "men"; 22 23 24 /* 受信した文字列を送信し、転送が終了していなければ次を受信する */ 25 while (recvMsgSize > 0) /* ゼロは転送の終了を意味する */ 26 { //文字列の判定と送信 27 if(strcmp(echoBuffer, qes)== 0{ 28 }else if(strcmp(echoBuffer, qes1)== 0){ 29 if (send(clntSocket, ans1, recvMsgSize, 0) != recvMsgSize) 30 DieWithError("send() failed"); 31 } 32 /* 受信するデータが残っていないか確認する */ 33 if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) 34 DieWithError("recv() failed"); 35 } 36 37 close(clntSocket); /* クライアントソケットをクローズする */ 38} 39

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

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

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

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

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

otn

2022/03/10 13:11

どこまでの部分で、期待通りの動きをして、どこから期待通りでないのか、確認してはどうでしょうか?
episteme

2022/03/10 15:19

↑せやね。ともかくechoBufferに入ってる文字列(?)をどこかでプリントしてはいかがかと。
jimbe

2022/03/10 17:59

> send(clntSocket, ans1, recvMsgSize, 0) 第三パラメータは間違っていると思います。
guest

回答1

0

ベストアンサー

windows/cygwin でやってみました。
クライアント側は送信後に同一ソケットから受信するならソケットをクローズ出来ません(※)ので、サーバの recv が 0 で戻ることはありません。
ですので、 recv が 0 を返すまで読み込んでから送信するというコードは期待した動作にはならないでしょう。

※ shutdown システムコールのことをすっかり忘れていました。 shutdown を使えば送信側だけを閉じることが出来ますので、クライアント側が送信後にそうすることが決まっていれば、サーバ側は『切断まで受信する』形で出来ます。

以下では '\0' を区切りとしています。

tcptest.c

c

1#include <stdio.h> 2#include <unistd.h> 3#include <string.h> 4#include <sys/types.h> 5#include <sys/socket.h> 6#include <netinet/in.h> 7#include <arpa/inet.h> 8 9void tcpclient(int port, char *message) { 10 int sock = socket(AF_INET, SOCK_STREAM, 0); 11 if(sock < 0) { 12 perror("socket"); 13 return; 14 } 15 16 struct sockaddr_in addr; 17 addr.sin_family = AF_INET; 18 addr.sin_port = htons(port); 19 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 20 21 connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); 22 23 if(send(sock, message, strlen(message)+1, 0) < 0) { //'\0'まで送る 24 perror("send"); 25 close(sock); 26 return; 27 } 28 29 char buf[256]; 30 int len; 31 for(int i=0; (len=recv(sock, &buf[i], sizeof(buf)-i,0)) > 0; i+=len); //切断まで 32 33 if(len < 0) { 34 perror("recv"); 35 close(sock); 36 return; 37 } 38 39 printf(buf); 40 41 close(sock); 42} 43 44void reply(int sock, char *message) { 45 if(send(sock, message, strlen(message)+1, 0) < 0) { 46 perror("send"); 47 } 48} 49 50struct { 51 char *request; 52 char *response; 53} DATA[] = { 54 { "年齢", "19" }, 55 { "性別", "men" }, 56 { NULL, NULL } //EOD 57}; 58 59void echo(int sock) { 60 char buf[256]; 61 62 for(int i=0, len; (len=recv(sock, &buf[i], sizeof(buf)-i,0)) > 0; i+=len) { 63 for(int j=0; j<len; j++) { 64 if(buf[i+j] == '\0') { //'\0'まで受け取っていたら 65 printf(buf); 66 for(int i=0; DATA[i].request != NULL; i++) { 67 if(strcmp(buf, DATA[i].request) == 0) { 68 reply(sock, DATA[i].response); 69 return; 70 } 71 } 72 reply(sock, "(error)"); 73 return; 74 } 75 } 76 } 77 perror("recv"); 78} 79 80void tcpserver(int port) { 81 int ss = socket(AF_INET, SOCK_STREAM, 0); 82 if(ss < 0) { 83 perror("socket"); 84 return; 85 } 86 87 struct sockaddr_in addr; 88 addr.sin_family = AF_INET; 89 addr.sin_port = htons(port); 90 addr.sin_addr.s_addr = INADDR_ANY; 91 if(bind(ss, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 92 perror("bind"); 93 close(ss); 94 return; 95 } 96 97 if(listen(ss, 10) < 0) { 98 perror("listen"); 99 close(ss); 100 return; 101 } 102 103 struct sockaddr_in caddr; 104 socklen_t csize = sizeof(caddr); 105 106// while(1) { 107 int sock = accept(ss, (struct sockaddr *)&caddr, &csize); 108 if(sock < 0) { 109 perror("accept"); 110 close(ss); 111 return; 112 } 113 114 echo(sock); 115 close(sock); 116// } 117 118 close(ss); 119} 120 121#define PORT 12345 122 123int main(int argc, char **argv) { 124 if(argc >= 2) tcpclient(PORT, argv[1]); 125 else tcpserver(PORT); 126 127 return 0; 128}

サーバ

plain

1F:\teratail_c\Debug>tcptest.exe 2年齢 3F:\teratail_c\Debug>tcptest.exe 4性別 5F:\teratail_c\Debug>tcptest.exe 6あいう

クライアント

plain

1F:\teratail_c\Debug>tcptest.exe 年齢 219 3F:\teratail_c\Debug>tcptest.exe 性別 4men 5F:\teratail_c\Debug>tcptest.exe あいう 6(error)

投稿2022/03/11 12:05

編集2022/03/12 17:22
jimbe

総合スコア12648

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問