weemiee
@weemiee (weemiee)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ソケット通信が思うように出来ない

Q&A

『Tera Term』を使用し、『Raspberry Pi』でのソケット通信を試みました。しかし、実行まではうまくいかず、通信は失敗したようでした。
※ソケット名は次のようにしています。

対象 変数名
ソケット(サーバ) sock_s
ソケット(クライアント) sock_c
接続済のソケット(サーバ) c_sock_s
サーバ
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define SERVER_PORT 8080
#define BUF_SIZE 1024

void transfer(int tf_sock){
	
	char send_buf[100], recv_buf[100];
	int send_size, recv_size;
	
	while (1) {
		
		recv_size = recv(tf_sock, recv_buf, sizeof(recv_buf), 0);
		if (recv_size == 1) {
			printf("recv error\n");
			exit(1);
		}
		
		if (recv_size == 0) {
			/* 受信サイズが0の場合は相手が接続閉じていると判断 */
			printf("connection ended\n");
			continue;
		}
		
		printf("%s\n", recv_buf);
		
	}
	
}

int main(){
	
	int sock_s = socket(AF_INET, SOCK_STREAM, 0);   //ソケットを作成
	if (sock_s == 1) {
		printf("ソケットエラーです\n");
		return 1;
	}
	
	//IPアドレスやポート番号の指定
	struct sockaddr_in sv_addr;
	memset(&sv_addr, 0, sizeof(struct sockaddr_in));
	sv_addr.sin_family = AF_INET;
	sv_addr.sin_port = htons((unsigned short)SERVER_PORT);
	sv_addr.sin_addr.s_addr = INADDR_ANY;
	
	if ( bind(sock_s, (struct sockaddr *)&sv_addr, sizeof(sv_addr)) == 1 ) {   //ソケット登録
	printf("bind error\n");
		close(sock_s);
		return 1;
	}
	
	while (1) {
		
		if ( listen(sock_s, SOMAXCONN) == 1 ) {   //接続待ち
			printf("listen error\n");
			close(sock_s);
			return 1;
		}
		
		printf("Waiting connect...\n");
		struct sockaddr_in get_addr;
		socklen_t len = sizeof(struct sockaddr_in);
		int c_sock_s = accept(sock_s, (struct sockaddr *)&get_addr, &len);   //接続要求の受け付け
		if (c_sock_s == 1) {
			printf("accept error\n");
			close(sock_s);
			return 1;
		}
		printf("Connected successfully.\n");
		
		transfer(c_sock_s);   //通信
		close(c_sock_s);
		
	}
	
	//クローズ
	close(sock_s);
	
}
クライアント
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define SERVER_PORT 8080
#define BUF_SIZE 1024

void transfer(int tf_sock){
	
	char send_buf[100], recv_buf[100];
	int send_size, recv_size;
	
	while(1){
		printf("Input Message here : ");
		scanf("%s", send_buf);   //サーバーへ送信する文字列を キーボードより読み込む
		
		send_size = send(tf_sock, send_buf, sizeof(send_buf), 0);   //送信
		if (send_size == 1) {
			printf("send error\n");
			exit(1);
		}
		
		recv_size = recv(tf_sock, &recv_buf, sizeof(recv_buf), 0);   //サーバからの応答を受信
		if (recv_size == 1) {
			printf("recv error\n");
			exit(1);
		}
		
	}
	
}

int main(){
	
	int sock_c = socket(AF_INET, SOCK_STREAM, 0);   //ソケットを作成
	if (sock_c == 1) {
		printf("ソケットエラーです\n");
		return 1;
	}
	
	//IPアドレスやポート番号の指定
	struct sockaddr_in ce_addr;
	memset(&ce_addr, 0, sizeof(struct sockaddr_in));
	ce_addr.sin_family = AF_INET;
	ce_addr.sin_port = htons((unsigned short)SERVER_PORT);
	ce_addr.sin_addr.s_addr = INADDR_ANY;
	
	printf("Start connecting...\n");
	if ( connect(sock_c, (struct sockaddr*)&ce_addr, sizeof(struct sockaddr_in)) == 1 ) {   //サーバーに接続要求送信
		printf("connect error\n");
		close(sock_c);
		return 1;
	}
	printf("Finish connect.\n");
	
	transfer(sock_c);   //通信
	
	close(sock_c);   //クローズ
	
}

サーバとクライアントともに、コンパイルは出来ました。
こちらとしては、while文によって文字列を繰り返し入力・送信出来るプログラムを想定していました。しかし、クライアント側は、文字列を入力してエンターキーを押したら、サーバ側に文字列が反映された(送信出来た)までは良かったものの、その後「Input Message here :」は表示されず、次の文字列を入力出来ずにそのまま動かなくなりました。恐らく、書いたプログラムに不備があるはずだと思っています。
どなたか、お力添え頂けると幸いです。アドバイスあれば是非お願いします。

0

3Answer

気になった点:

  • エラー判定は == 1 ではなく == -1 です。
  • クライアントは送信後に受信を待っているのに、サーバ側は何も送信していない
0Like

Comments

  1. まずは、クライアント側で recv するのをやめてみてはいかがですか?

@shiracamusさん、ご回答ありがとうございます。

エラー判定は == 1 ではなく == -1 です。

そうでしたね。自分にはまだreturn 1と混同してしまう癖があるみたいです。すぐにでもなおしていきます!

クライアントは送信後に受信を待っているのに、サーバ側は何も送信していない

これはつまり、サーバ側のプログラムに

クライアント
recv_size = recv(tf_sock, &recv_buf, sizeof(recv_buf), 0);

に対応するsend関数を加えれば良いという事でしょうか?こちらの方について教えてくださると幸いです。

0Like

Your answer might help someone💌