TCP を使ってデータを送信します。 自宅無線LANのローカルで通信します。
PC からスマホに文字データ「abcdefg」を送信します。
PCをクライアント、スマホをサーバーとします。データの終了の見極めは、バイト長とします。
PC側コード(送信側 / クライアント)
# 送信側(TCP クライアント)
import socket
TARGET_IP = "192.168.0.235" # ←受信側のIP
TARGET_PORT = 5000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((TARGET_IP, TARGET_PORT))
message = b"abcdefg"
sock.sendall(message)
print("送信:", message, "→", TARGET_IP, TARGET_PORT)
sock.close()
PC側 コードの解説
全体の流れ
この送信プログラムは、
TCP ソケットを作る → 接続する → メッセージを送る → 終わり
という構成です。 UDP と違い、TCP は「接続してから送る」必要があります。
コードの分解と解説
1. import socket
Python の標準ライブラリ。 ネットワーク通信の基本機能が入っています。
2. 送信先の設定
TARGET_IP = "192.168.0.235"
TARGET_PORT = 5000
- TARGET_IP:受信側(サーバ)の IP
- TARGET_PORT:受信側が
bind()して待っているポート番号
TCP も UDP と同じく、相手の IP とポート番号が必要です。
3. TCP ソケットを作る
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
AF_INET→ IPv4SOCK_STREAM→ TCP を使う
UDP の SOCK_DGRAM と違い、TCP はストリーム通信です。
4. サーバに接続する
sock.connect((TARGET_IP, TARGET_PORT))
TCP は「接続してから送る」方式なので、 まずサーバに接続します。
5. 送るデータを作る
message = b"abcdefg"
TCP も UDP と同じく バイト列を送ります。
6. データを送信
sock.sendall(message)
sendall()はデータをすべて送るまでブロックする- TCP はパケット分割を OS が自動で行うため、
sendall()が安全
7. 送信ログ
print("送信:", message, "→", TARGET_IP, TARGET_PORT)
8. ソケットを閉じる
sock.close()
TCP は接続型なので、最後に必ず閉じます。
スマホ側コード(受信側 / サーバ)
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("0.0.0.0", 5000))
sock.listen(1)
print("waiting...")
conn, addr = sock.accept()
print("connect:", addr)
# Receive a fixed-length message of 7 bytes
expected = 7
received = b""
while len(received) < expected:
chunk = conn.recv(expected - len(received))
if not chunk:
break
received += chunk
print("received:", received.decode(), "from", addr)
conn.close()
sock.close()
スマホ側 コードの解説
全体の流れ
- TCP ソケットを作る
- ポート 5000 を開けて待ち受ける
- クライアント(PC)が接続してくる
- データを受信する
- 表示する
UDP と違い、TCP は 接続(accept) が必要です。
コードの分解と解説
1. ソケットライブラリを読み込む
import socket
2. TCP ソケットを作る
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCK_STREAM→ TCP- 「TCP 用の受信箱」を作るイメージ
3. ポート 5000 を開けて待ち受ける
sock.bind(("0.0.0.0", 5000))
"0.0.0.0"→ すべてのネットワークインターフェースで受信5000→ このスマホ(または PC)の受信ポート番号
4. 接続待ち行列を作る
sock.listen(1)
print("waiting...")
sock.listen(1) の「1」は、接続待ち行列の長さ。
5. クライアントからの接続を受け付ける
conn, addr = sock.accept()
print("connect:", addr)
accept() は クライアントからの接続要求が来るまで待つ(ブロックする) 関数です。 クライアントが connect() を呼ぶと接続が成立し、accept() が解除されて次の行へ進みます。
addr には (クライアントIPアドレス, クライアント側ポート番号) のタプルが入ります。
(補足)クライアント側のポート番号は OS が毎回自動的に割り当てるため、接続のたびに異なるポート番号になるのが普通です(固定ではありません)。
6. データを受信(固定長バイト)
# Receive a fixed-length message of 7 bytes
expected = 7
received = b""
while len(received) < expected:
chunk = conn.recv(expected - len(received))
if not chunk:
break
received += chunk
固定長受信が必要になる背景
TCP は ストリーム(バイトの流れ) であり、次の性質があります。
- 送信したデータは 分割されることがある
- 複数の send が まとめられることがある
- recv() は「届いた分だけ返す」
- メッセージの終わりは TCP が教えてくれない
- しかし 順番は必ず保証される
そのため、アプリ側で「どこまでが1メッセージか」を決める必要があります。 固定長方式はその最もシンプルで堅牢な方法です。
コードの各行が果たす役割
1. 必要なバイト数を決める
expected = 7
received = b""
- 今回は 7 バイトが 1 メッセージ と決めている
receivedは受信した断片(chunk)をつなげていくバッファ
2. 必要なバイト数が揃うまでループする
while len(received) < expected:
- TCP は分割されるため、1 回の recv で 7 バイト揃うとは限らない
- だから 必要な長さに達するまで繰り返す
3. 足りない分だけ recv する
chunk = conn.recv(expected - len(received))
- すでに受け取った分を除いた「残りの必要バイト数」だけ要求する
- ただし実際に届く量は OS が決めるので、もっと少ないこともある
- これが chunk(断片)
4. if not chunk: の意味
if not chunk:
break
ここが最も誤解されやすい部分ですが、意味はこうです。
recv() が空の b”” を返すのは「相手が切断した」時
Python では次の値は「偽(False)」とみなされます。
0""b""← 今回これ[]None
つまり if not chunk: は
chunk が空(b””)なら True → 相手が切断したのでループを終了する
という意味です。
これがないと無限ループになる
相手が 7 バイト送る前に切断した場合:
- recv → b”ABC”
- recv → b””(切断)
if not chunk: がないと、 len(received) < expected が永遠に True のままになり、無限ループします。
5. 断片をつなげていく
received += chunk
- TCP は分割されるので、断片をつなげて 7 バイトにする
- 順番は TCP が保証してくれるので安心して連結できる
7. 受信内容を表示
print("received:", received.decode(), "from", addr)
8. 接続を閉じる
conn.close()
sock.close()
TCP は接続型なので、最後に必ず閉じます。
結果
最初にスマホ側(サーバ)を起動。 次に PC 側(クライアント)を起動します。
PC から送信した「abcdefg」が表示されます。
スマホ側(受信)画面




人気ブログランキング ブログパーツ