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

[Python3] UDP でデータを送受信する方法

More than 1 year has passed since last update.

環境

python 3.x
OS は問わない

送信側

udpsend.py
from socket import *

## UDP送信クラス
class udpsend():
    def __init__(self):

        SrcIP = "127.0.0.1"                             # 送信元IP
        SrcPort = 11111                                 # 送信元ポート番号
        self.SrcAddr = (SrcIP,SrcPort)                  # アドレスをtupleに格納

        DstIP = "127.0.0.1"                             # 宛先IP
        DstPort = 22222                                 # 宛先ポート番号
        self.DstAddr = (DstIP,DstPort)                  # アドレスをtupleに格納

        self.udpClntSock = socket(AF_INET, SOCK_DGRAM)  # ソケット作成
        self.udpClntSock.bind(self.SrcAddr)             # 送信元アドレスでバインド

    def send(self):

        data = "Hello"
        data = data.encode('utf-8')                     # バイナリに変換

        self.udpClntSock.sendto(data, self.DstAddr)     # 宛先アドレスに送信

udp = udpsend()     # クラス呼び出し
udp.send()          # 関数実行
  • socket の引数の AF_INET は IPv4 用。AF_INET6 は IPv6 用
  • SOCK_DGRAM は UDP 用。TCP の場合は SOCK_STREAM
  • DstAddr でバインドしなくてもデータを送信できるが、バインドしないと送信元アドレスが固定されない
    • 受信側で送信元を指定する場合は設定しておいたほうが吉
  • sendto するときにデータをバイナリに変換する必要がある
  • "127.0.0.1" は自分自身のIPアドレスなので、任意に変更すると異なる機器間で通信が可能

受信側

udprecv.py
from socket import *

## UDP受信クラス
class udprecv():
    def __init__(self):

        SrcIP = "127.0.0.1"                             # 受信元IP
        SrcPort = 22222                                 # 受信元ポート番号
        self.SrcAddr = (SrcIP, SrcPort)                 # アドレスをtupleに格納

        self.BUFSIZE = 1024                             # バッファサイズ指定
        self.udpServSock = socket(AF_INET, SOCK_DGRAM)  # ソケット作成
        self.udpServSock.bind(self.SrcAddr)             # 受信元アドレスでバインド

    def recv(self):
        while True:                                     # 常に受信待ち

            data, addr = self.udpServSock.recvfrom(self.BUFSIZE)
                                                        # 受信
            print(data.decode(), addr)                  # 受信データと送信アドレス表示

udp = udprecv()     # クラス呼び出し
udp.recv()          # 関数実行
  • 受信側では受信するアドレスでバインドして受信を待つ
    • 送信アドレスを指定したりせず全てを受け入れる
  • print で送信したデータと送信元のアドレスを表示する
  • バッファサイズはデータサイズによって変更してほしい

実行方法

コンソールを2つ起動。
cd ~~ で .pyファイルがある場所へディレクトリ移動。

受信側(コンソール①)

python3 udprecv.py

これで受信待ち状態になる。

送信側(コンソール②)

python3 udpsend.py

"Hello" を1回送信する。

実行結果(コンソール①)

Hello ('127.0.0.1', 11111)

まとめ

通信プロトコルの一つであるUDPでデータを送受信することができた。
個人的にひっかかったのは、アドレスをバインドする意味が始め分からなかったところである。
送信側で送信先を指定しないと、、と思って送信先アドレスでバインドするとうまくいかなかった。
要するに、間違っていたのは
「ソケットをバインドする」=「自らのアドレスで固定する」
というところだった。

新卒、勉強不足。

解釈に間違いがあれば指摘してほしい。

kashitaku
新卒研究開発者
Why not register and get more from Qiita?
  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