環境
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でデータを送受信することができた。
個人的にひっかかったのは、アドレスをバインドする意味が始め分からなかったところである。
送信側で送信先を指定しないと、、と思って送信先アドレスでバインドするとうまくいかなかった。
要するに、間違っていたのは
「ソケットをバインドする」=「自らのアドレスで固定する」
というところだった。
新卒、勉強不足。
解釈に間違いがあれば指摘してほしい。