Programming Tips blog

テキトーにTIPSを紹介します

ラズパイでソケット通信(Pythonサーバ - C++クライアント)

緒言

 特にラズパイでということもないのですが、ソケット通信をしてみました。
 サーバはPythonで、クライアントはC++で書いてみました。いわば、異種格闘技戦って感じ。
 cmakeファイルまで提示してくれるサイトが少ないので、ここに書いてみました。

ハードウェア

ソフトウェア

Pythonサーバ

#!/usr/bin/python3
# -*- coding: utf-8 -*-


import socket
import select


# メイン関数
# 引数:なし
# 返値:なし
def main():
	# 変数定義、初期化
	kill_flag = False
	quit_flag = False
	local_port = 2345				# ローカルポート番号
	ack = "ACK"						# 確認応答メッセージ
	data = ""						# 受信文字列
	
	# サーバソケット作成
	server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	# サーバソケットバインド
	server_socket.bind(("", local_port))
	# サーバソケットリスン
	server_socket.listen()
	
	while not kill_flag:
		# クライアントからの接続をselect待ちする
		rready, wready, xready = select.select([server_socket], [], [], 1)
		# アクセスがあった場合
		for r in rready:
			# accept
			connection_socket, address = server_socket.accept()
			while not kill_flag:
				# 受信をselect待ちする
				r1ready, w1ready, x1ready = select.select([connection_socket], [], [], 1)
				# 受信があった場合
				for r1 in r1ready:
					# recv
					data = connection_socket.recv(1024).decode("utf-8")
					# 相手からcloseがあった場合
					if len(data) == 0:
						# コネクションソケットをcloseする
						connection_socket.close()
						quit_flag = True
						break
					# 表示する
					print(data)
					# 送信する
					connection_socket.send(ack.encode("utf-8"))
				if quit_flag:
					quit_flag = False
					break
	
	# サーバソケットclose
	server_socket.close()
	return


# メイン関数
# 引数:なし
# 返値:なし
# 備考:main()に投げるだけ
if __name__ == "__main__":
	main()

C++クライアント

cmake

# CMakeのバージョンを設定
cmake_minimum_required(VERSION 3.25)
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# プロジェクト名と使用する言語を設定
project(clienttest CXX)

# 取り込むソースコード
set(client_src
	clienttest02.cpp
)

# おまじない
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-long-long -pedantic")

# servertestという実行ファイルをserver_srcから作成
add_executable(clienttest ${client_src})

c++

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <cstring>

int main(void) {
    int client_socket;
    struct sockaddr_in addr;
    int port = 2345;                    // サーバポート番号
    std::string data = "Hello World!";  // 送信文字列
    char received_data[1024];           // 受信文字列
 
    // socket
    client_socket = socket(AF_INET, SOCK_STREAM, 0);
 
    // アドレス、ポート番号設定
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 
    // connect
    connect(client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));

    // c_strに変換する
    const char* m_data{data.c_str()};

    // 10回繰り返す
    for(int i = 0; i < 10; i++) {
        // 送信
        send(client_socket, m_data, std::strlen(m_data), 0);
        // 受信
        ssize_t received_size = recv(client_socket, received_data, 1024, 0);
        // 文字列の最後に「\0」をつける
        received_data[received_size] = '\0';
        // 表示する
        std::cout << "Received:" << received_data << std::endl;
    }
 
    // close
    close(client_socket);
    return 0;
}

 ランキングに参加しています。下記バナーをクリックしていただけるとありがたいです。