Python & Raspberry Pi 開発ブログ ☆彡

PythonとRaspberry Piの基本的な使い方をわかりやすく解説。初心者、入門者必見!!

Python Socket通信の仕方:クライアント編

今回はRaspberry Piでソケット通信(クライアント側)を行う方法を紹介したいと思います。デバイスを制御する時は、Raspberry Piがクライアントになるので、よく使いますね。また、下記のサーバー側のブログと合わせて読んでください。

www.raspberrypirulo.net

サンプルコードの内容

ソケット通信はクライアント ⇔ サーバー間でデータをやり取りする仕組みになっています。下記のサンプルコードは以下のように動作します。
・クライアントから文字を入力
・入力した文字列をサーバーに送信
・サーバーがデータを受け取る
・受け取ったデータをそのままクライアントに送信

構成

・サーバー:Raspberry Pi IPアドレス 192.168.1.10  ポート:12345
・クライアント:Raspberry Pi IPアドレス 192.168.1.15 ポート:12345

クライアント側のサンプルコード ①

今回、2パターン紹介したいと思います。①は、通信する毎にソケットのオープン/クローズをする方法です。現在のハードウェアスペックであれば、全く問題ありませんが、こちらのほうが処理は重たいです。 それではコードの説明をしてきます。

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
⇒ socketモジュールをインスタンス化 。with文を抜けると自動的にソケットをcloseしてくれる。

sock.connect( (self.host, self.port) )
⇒ サーバー側のIPアドレスとポートを設定

下記コードにもコメントで説明を加えていますので、参考にしてください。

import socket
import time
from datetime import datetime

HOST_IP = "192.168.0.10" # 接続するサーバーのIPアドレス
PORT = 12345 # 接続するサーバーのポート
DATESIZE = 1024  # 受信データバイト数

class SocketClient():

    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.socket = None

    def send_recv(self, input_data):
        
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect((self.host, self.port))
            print('[{0}] input data : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), input_data) )
            sock.send(input_data.encode('utf-8')) # 入力データをサーバーへ送信
            rcv_data = sock.recv(DATESIZE) # サーバーからのデータを受信
            rcv_data = rcv_data.decode('utf-8')
            print('[{0}] recv data : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rcv_data) )

if __name__ == '__main__':

    client = SocketClient(HOST_IP, PORT)
    while True:
        input_data = input("send data:") # ターミナルから入力された文字を取得
        client.send_recv(input_data)

クライアント側のサンプルコード ②

こちらは、ソケットのオープンをはじめの1回だけするサンプルコードです。

import socket
import time
from datetime import datetime

HOST_IP = "192.168.0.10" # 接続するサーバーのIPアドレス
PORT = 12345 # 接続するサーバーのポート
DATESIZE = 1024 # 受信データバイト数
INTERVAL = 3 # ソケット接続時のリトライ待ち時間
RETRYTIMES = 5 # ソケット接続時のリトライ回数

class SocketClient():

    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.socket = None

    def connect(self):
    
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)       
    
        for x in range(RETRYTIMES): # RETRYTIMESの回数だけリトライ
            try:
                client_socket.connect((self.host, self.port)) # サーバーとの接続
                self.socket =  client_socket
                print('[{0}] server connect -> address : {1}:{2}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), self.host, self.port) )
                break
            except socket.error:
                print('[{0}] retry after wait{1}s'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(INTERVAL)) )
                time.sleep(INTERVAL) # 接続を確立できない場合、INTERVAL秒待ってリトライ
 
    def send(self): # サーバーへデータ送信関数
        input_data = input("send data:") # ターミナルから入力された文字を取得
        print('[{0}] input data : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), input_data) )
        input_data = input_data.encode('utf-8')
        self.socket.send(input_data) # データ送信
    
    def recv(self): # サーバーからデータ受信関数
        rcv_data = self.socket.recv(DATESIZE) # データ受信
        rcv_data = rcv_data.decode('utf-8')
        print('[{0}] recv data : {1}'.format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), rcv_data) )
        return rcv_data
    
    def send_rcv(self):
        self.send()
        return senf.recv()
        
    def close(self):
    
        self.socket.close() # ソケットクローズ
        self.socket = None
             
if __name__ == '__main__':
    
    client = SocketClient(HOST_IP, PORT)
    client.connect() # はじめの1回だけソケットをオープン
    
    while True:
        if client.socket is not None:
            if client.send_rcv() == 'quit': # quitが戻ってくるとソケットをクローズして終了
                client.close()
        else:
            break

①、②どちらもターミナルで入力した文字がエコーバックしてくれば、成功です。 以上でクライアント側の説明は終了です。

ラズパイ ソフトウェアに戻る
ラズパイ ハードウェアに戻る
トップページに戻る