Help us understand the problem. What is going on with this article?

Python3系にてマルチスレッドでUDP通信

More than 1 year has passed since last update.

主に自分用のメモです。

はじめに

  • Pythonでメインのプログラムの傍らUDP通信をしたい
  • マルチスレッドで通信内容を共有したい

ということで複数スレッドを立てて,片方のスレッドでUDPを受信しつつもう片方のスレッドで別の作業をできるようにします。

参考にしたページ群を以下に追記していきます。
- https://qiita.com/slowsingle/items/20d4d601a85470725eb3

マルチスレッド

簡単なマルチスレッドでよければPythonのthreadingを用います。

UDP通信

以下の記事をソケット通信実装の参考にしました。

UDP通信とマルチスレッドに関する記事はTCPで通信しており,UDPに変える必要がありますね。

UDP クライアント

標準入力から入力を取得して送信するクライアントのプログラムをかきました。

client.py

# coding: utf-8
from socket import *
HOST = gethostname()
PORT = 34512
BUFSIZE = 1024
ADDR = (gethostbyname(HOST), PORT)
USER = 'Client'
udpClntSock = socket(AF_INET, SOCK_DGRAM)
while True:
    data = input('%s > ' % USER) # 標準入力からのデータ入力
    udpClntSock.sendto(data.encode('utf-8'), ADDR) # データ送信
    #udpClntSock.setblocking(0)# Non blocking
    if not data:
        break
udpClntSock.close()

UDPなのでソケットを作ってぶち込むだけです。

サーバー側

サーバー側では別のスレッドを立ててそこで受信を待ちつつ,main関数で受信した文字列を閲覧しています。
グローバル変数でも良いらしいですが,クラス変数を参照することによってわかりやすくなっています。

自分的ポイントは

  • クラスの定義でThreadを継承
  • 受信データをクラス変数に格納してmainで読めば良い

ってとこでしょうか。

import threading
import time
from socket import *

class ServerThread(threading.Thread):
    def __init__(self, PORT=34512):
        threading.Thread.__init__(self)
        self.data = 'hoge'
        self.kill_flag = False
        # line information
        self.HOST = gethostname()
        self.PORT = PORT
        self.BUFSIZE = 1024
        self.ADDR = (gethostbyname(self.HOST), self.PORT)
        # bind
        self.udpServSock = socket(AF_INET, SOCK_DGRAM)
        self.udpServSock.bind(self.ADDR) # HOST, PORTでbinding

    def run(self):
        while True:
            try:
                data, self.addr = self.udpServSock.recvfrom(self.BUFSIZE) # データ受信
                self.data = data.decode()
            except:
                pass

if __name__ == '__main__':
    th = ServerThread()
    th.setDaemon(True)
    th.start()

    while True:
        if not th.data:
            break
        print(th.data)
        time.sleep(0.1)

UDPサーバー

非同期通信を行ったブログが参考になります。

メモなど

strとbyte型の変換

Python3ではソケットを送る際にstr型からbyte型への変換を求められます。

str型はともかく,byte型とはb'hogefuga'で表される文字列で,''の前にbを入れればOKです。

また,encodeとdecodeで変換できます。

>>> 'hogefuga'.encode('utf-8')
b'hogefuga'
>>> b'hogefuga'.decode('utf-8')
'hogefuga'

このutf-8を入力しないでも一応変換してくれますがデフォルトの変換がどのようなものかわからないので一応入れておくようにしましょう。

非同期通信を用いる

マルチスレッドの他にもノンブロッキングプロセスという仕組みを用いて通信待ちをしながら別の処理ができます。
気が向いたら追記します(PCの電池が切れそう)

ノンブロッキングプロセスに関してはこちら

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away