LinuxやWindowsでのプロセス間通信(exe間通信)や、機器間でのデータやり取りに欠かせないのが「ソケット通信」です。
私は業務でもデータの引き渡しによくソケット通信を利用しますが、実はPythonでも標準ライブラリを使って非常に簡単に実装できます。
この記事では、信頼性の高いTCPと、高速なUDPの両方について、そのまま使えるサンプルコード付きで解説します。
もっと深く制御したい方へ
TCP/UDPといった標準的なプロトコルではなく、EthernetヘッダやIPヘッダから自分で構築して「Rawパケット」を送信したい場合は、以下の記事を参考にしてください。
1. TCPとUDP、どちらを使うべき?
実装の前に、まずはTCPとUDPの違いを整理しておきましょう。
| 特徴 | TCP (SOCK_STREAM) | UDP (SOCK_DGRAM) |
| 信頼性 | 高い(再送制御あり) | 低い(送りっぱなし) |
| 速度 | 普通(接続手順が必要) | 高速 |
| 主な用途 | ファイル転送、HTTP、確実なデータ送受信 | リアルタイム動画、センサーデータ送信 |
基本的には「データの欠落が許されないならTCP」、「速度やリアルタイム性が最優先ならUDP」と使い分けます。
2. TCP通信のサンプルコード
まずは、接続を確立してから通信を行うTCPの例です。
Server側 (tcp_server.py)
import socket
def create_tcp_server(ip, port):
# SOCK_STREAMを指定してTCPソケットを作成
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((ip, port))
server.listen(1)
return server
if __name__ == '__main__':
IP_ADDR = '127.0.0.1'
PORT = 12345
server = create_tcp_server(IP_ADDR, PORT)
print(f"TCP Server待機中... ({IP_ADDR}:{PORT})")
# クライアントからの接続待ち
(con, client) = server.accept()
print("クライアント接続成功:", client)
try:
# データの送信 (bytearray型)
x = bytearray([1, 2, 3, 4])
con.send(x)
# データの受信
while True:
data = con.recv(1024)
if not data:
break
print("受信データ(HEX):", data.hex())
break
finally:
con.close()
server.close()
print("Server終了")Client側 (tcp_client.py)
import socket
def create_tcp_client(ip, port):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((ip, port))
return client
if __name__ == '__main__':
IP_ADDR = '127.0.0.1'
PORT = 12345
con = create_tcp_client(IP_ADDR, PORT)
print("Serverに接続しました")
# 受信
data = con.recv(1024)
print("受信データ(HEX):", data.hex())
# 送信
x = bytearray([5, 6, 7, 8])
con.send(x)
con.close()
print("Client終了")
3. UDP通信のサンプルコード
次に、接続不要でいきなりデータを送受信するUDPの例です。
Server側 (udp_server.py)
import socket
def start_udp_server(ip, port):
# SOCK_DGRAMを指定してUDPソケットを作成
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind((ip, port))
return server
if __name__ == '__main__':
IP_ADDR = '127.0.0.1'
PORT = 12345
server = start_udp_server(IP_ADDR, PORT)
print(f"UDP Server待機中... ({IP_ADDR}:{PORT})")
while True:
# recvfromでデータと送信元アドレスを取得
data, addr = server.recvfrom(1024)
print(f"受信元: {addr}, データ: {data.hex()}")
# 受信した相手に返信
response = bytearray([0xAA, 0xBB])
server.sendto(response, addr)
break
server.close()Client側 (udp_client.py)
import socket
if __name__ == '__main__':
IP_ADDR = '127.0.0.1'
PORT = 12345
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 送信先を指定してデータを投げる (connect不要)
msg = bytearray([0xCC, 0xDD])
client.sendto(msg, (IP_ADDR, PORT))
# 返信待ち
data, server_addr = client.recvfrom(1024)
print(f"Serverからの返信: {data.hex()}")
client.close()4. プログラムの解説
ソケットの生成
どちらの通信も socket.socket() で作成しますが、第2引数が異なります。
- TCP:
socket.SOCK_STREAM - UDP:
socket.SOCK_DGRAM
送受信の関数の違い
- TCPの場合:一度
connectやacceptで接続が確立されると、相手が固定されるためsend()/recv()を使います。 - UDPの場合:接続という概念がないため、送信のたびに宛先を指定する
sendto()を使い、受信時はrecvfrom()で送り主の情報も一緒に受け取ります。
UDP使用時の注意点
UDPはデータロストが発生しても検出できません。もしUDPで信頼性を確保したい場合は、アプリケーション層(自分で書くプログラム側)で「届いたら返事を出す」「返事がなければ再送する」といった仕組みを実装する必要があります。
そのため、特別な理由がなければ、まずはTCPから検討することをおすすめします。
まとめ
Pythonのソケット通信は、標準ライブラリだけで完結し、Windows/Linux問わず同じ書き方で動作します。
- 確実な通信ならTCP
- 速度重視ならUDP
- パケットを1から作りたいならRawパケット(Scapy等)
これらを使い分けることで、デバイス制御や自作アプリ間の連携がより柔軟に行えるようになります。ぜひ皆さんの開発に役立ててください!


コメント