緒言
特にラズパイでということもないのですが、ソケット通信をしてみました。
サーバはC++で、クライアントはPythonで書いてみました。いわば、異種格闘技戦って感じ。
cmakeファイルまで提示してくれるサイトが少ないので、ここに書いてみました。
ハードウェア
- Raspberry Pi 5 Model B 8GB RAM
ソフトウェア
- Raspberry Pi OS Lite Bookworm
- cmake
- g++
- Python
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) find_package(Threads REQUIRED) # プロジェクト名と使用する言語を設定 project(servertest CXX) # 取り込むソースコード set(server_src servertest04.cpp ) # おまじない set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-long-long -pedantic") # servertestという実行ファイルをserver_srcから作成 add_executable(servertest ${server_src}) # スレッドへリンク target_link_libraries(servertest Threads::Threads)
C++
#include <iostream> #include <thread> #include <vector> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <cstring> void BridgeConnectionThread(int connection_socket) { char buffer[1024] = {0}; const char *ack = "ACK"; int16_t i = 0; while(true) { // データを受信する int received_size = recv(connection_socket, buffer, sizeof(buffer), 0); // 相手からcloseがコールされた場合 if(received_size == 0) { std::cout << i << "Close" << std::endl; break; } // recvでエラーが発生した場合 else if(received_size < 0) { std::cerr << "Clushed Connection" << std::endl; close(connection_socket); return; } // char[]をstringに変換する std::string buff(buffer, sizeof(buffer) / sizeof(buffer[0])); // 送られてきたメッセージを表示する std::cout << i << "Message from client:" << buff << std::endl; // データを送信する send(connection_socket, ack, strlen(ack), 0); std::cout << "send ACK" << std::endl; i++; } // コネクションソケットをcloseする close(connection_socket); return; } int main() { int server_socket, connection_socket; struct sockaddr_in server_address, connection_address; socklen_t addrSize; // int addrlen = sizeof(address); // std::vector<std::thread> threads; // socket server_socket = socket(AF_INET, SOCK_STREAM, 0); if(server_socket == -1) { std::cerr << "Socket creation failed" << std::endl; exit(1); } // アドレスの準備 server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(2345); // bind if(bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) != 0) { std::cerr << "Socket bind failed" << std::endl; exit(1); } // listen if(listen(server_socket, 5) != 0) { std::cerr << "Listen failed" << std::endl; exit(1); } while(true) { addrSize = sizeof(connection_address); connection_socket = accept(server_socket, (struct sockaddr *)&connection_address, (socklen_t*)&addrSize); if(connection_socket < 0) { continue; } std::thread ConnectionThread(BridgeConnectionThread, connection_socket); ConnectionThread.detach(); } close(server_socket); return 0; }
Pythonクライアント
#!/usr/bin/python3 # -*- coding: utf-8 -*- import socket import time # メイン関数 # 引数:なし # 返値:なし def main(): # 変数定義、初期化 server_address = "127.0.0.1" # サーバIPアドレス server_port = 2345 # サーバポート番号 recv_buffer = 1024 # 受信バッファサイズ message = "Hello World!" # 送信文字列 data = "" # 受信文字列 # クライアントソケット作成 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # サーバに接続する client_socket.connect((server_address, server_port)) for i in range(50): # メッセージを送信する client_socket.send((str(i) + ":" + message).encode("utf-8")) # 確認応答メッセージを受信する data = client_socket.recv(recv_buffer).decode("utf-8") print(str(i) + ":" + data) # クライアントソケットをcloseする client_socket.close() return # メイン関数 # 引数:なし # 返値:なし # 備考:main()に投げるだけ if __name__ == "__main__": main()
ランキングに参加しています。下記バナーをクリックしていただけるとありがたいです。