Pythonによるソケット通信の基礎:ネットワークの仕組みを理解する
![]()
【Yuki】
Hirokiくん、こんにちは。今日はPythonを使って「ソケット通信」について学んでいこうと思います...。
ソケット通信というのは、ネットワークを通じて別のプログラムとデータをやり取りするための、もっとも基本的な仕組みなんです。私たちが普段使っているWebサイトの閲覧や、メッセージアプリの裏側でも、このソケット通信が基盤として動いていることが多いんですよ。
![]()
【Hiroki】
Yukiさん、よろしくお願いします!ソケット通信って名前は聞いたことがありますが、具体的にどうやってプログラム同士が会話しているのか、イメージがわかなくて...。初心者でも大丈夫でしょうか?
![]()
【Yuki】
大丈夫ですよ...。少しずつ、仕組みを紐解いていきましょうね。
ソケットというのは、よく「ネットワーク上のコンセント」や「窓口」に例えられます。コンピュータ同士が通信をする際、そのデータの入り口や出口となるのがソケットだと考えてみてください。
ソケット通信の基本概念:IPアドレスとポート番号
![]()
【Yuki】
まず、ソケット通信を理解するために欠かせないのが「IPアドレス」と「ポート番号」です。
IPアドレスは、ネットワーク上での「住所」のようなものです。どのコンピュータにデータを送るかを決めるために使われます。
そして、そのコンピュータの中に、たくさんのアプリケーションが動いていますよね?その中のどの「窓口」でデータを受け取るかを指定するのが「ポート番号」なんです...。
![]()
【Hiroki】
なるほど。住所がIPアドレスで、その家の中にある「特定の窓」がポート番号、という感じですね?
![]()
【Yuki】
ええ、その通りです...。とっても分かりやすい例えだと思います。
ポート番号は0から65535まであって、0から1023までは「ウェルノウンポート」と呼ばれ、HTTP(80番)やHTTPS(443番)のように、あらかじめ用途が決まっていることが多いですね。自分でプログラムを作る時は、一般的に49152番以降の自由な番号を使うのが安全かもしれません。
通信プロトコルの選択:TCPとUDP
![]()
【Yuki】
次に、データの運び方についてお話しします。ソケット通信には主に「TCP」と「UDP」という2つの方式があります。
TCPは、相手と「今から送りますよ」「はい、受け取りました」と確認を取り合いながら通信する方式です。信頼性が高いので、Web閲覧やメールなどに使われます。
一方でUDPは、相手の状況を確認せずにデータを一方的に送りつける方式です。速いですが、データが消えてしまう可能性もあります。動画配信やオンラインゲームなど、リアルタイム性が重視される場面で使われることが多いですね。
![]()
【Hiroki】
今回は、どちらを練習するんですか?
![]()
【Yuki】
今回は、より確実なデータのやり取りを学べる「TCP」を使った通信に挑戦してみましょう。Pythonには socket という標準ライブラリがあって、それを使うことで簡単に実装できるんですよ。
Pythonでサーバー側を実装する
![]()
【Yuki】
それでは、実際にコードを書いてみましょう。まずはデータを受け取る側の「サーバー」プログラムからです。
以下のコードは、クライアントからの接続を待ち受け、メッセージを受け取って、返事をするシンプルなものです。
import socket
def start_server():
# 1. ソケットオブジェクトの作成
# AF_INETはIPv4、SOCK_STREAMはTCPを意味します
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
# 2. IPアドレスとポート番号を紐付ける
# '127.0.0.1'は自分自身を指すローカルホストです
host = '127.0.0.1'
port = 50000
server_socket.bind((host, port))
# 3. クライアントからの接続を待つ状態にする
server_socket.listen(1)
print(f"サーバーが起動しました。{host}:{port} で待機中です...")
# 4. クライアントの接続を受け入れる
client_socket, address = server_socket.accept()
with client_socket:
print(f"クライアントが接続してきました: {address}")
# 5. データの受信
# 受信バッファサイズを1024バイトに設定します
data = client_socket.recv(1024)
if not data:
return
# 受信データはバイト形式なので文字列にデコードします
message = data.decode('utf-8')
print(f"受信メッセージ: {message}")
# 6. データの送信(返信)
response = f"メッセージ「{message}」を受け取りました。"
client_socket.sendall(response.encode('utf-8'))
if __name__ == "__main__":
start_server()
![]()
【Hiroki】
コードの中に AF_INET や SOCK_STREAM といった言葉が出てきましたね。
![]()
【Yuki】
そうですね、これらはソケットの種類を指定するための定数です...。
AF_INET は「IPv4」という形式のIPアドレスを使うことを示し、SOCK_STREAM は「TCP」を使って通信することを指示しています。
あと、bind() で住所を登録し、listen() で「聞き耳を立てる」状態にし、accept() で実際に「繋がる」のを待つ...という流れがサーバー側の特徴ですね。
Pythonでクライアント側を実装する
![]()
【Yuki】
今度は、サーバーにメッセージを送る「クライアント」側を作ってみましょう。サーバー側が起動している状態で実行する必要があります。
import socket
def start_client():
# 1. ソケットオブジェクトの作成
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
# 2. サーバーに接続する
host = '127.0.0.1'
port = 50000
client_socket.connect((host, port))
# 3. データの送信
message = "こんにちは、Yukiさん!ソケット通信の練習中です。"
client_socket.sendall(message.encode('utf-8'))
# 4. サーバーからの返信を受信
data = client_socket.recv(1024)
print(f"サーバーからの返信: {data.decode('utf-8')}")
if __name__ == "__main__":
start_client()
![]()
【Hiroki】
サーバー側よりも少しシンプルですね!connect() を使って自分から繋ぎに行くところがポイントでしょうか。
![]()
【Yuki】
その通りです。クライアントは「誰に繋ぐか」が分かればいいので、bind() や listen() は必要ありません...。
ただ、一つ気をつけてほしいのは、ネットワークを通るデータはすべて「バイト列(bytes)」であるという点です。
文字列をそのまま送ることはできないので、encode('utf-8') でバイト列に変換し、受け取った時は decode('utf-8') で文字列に戻す必要があります。ここを忘れると、エラーになってしまうかもしれません。
エラー処理とタイムアウトの設定
![]()
【Hiroki】
もしサーバーが動いていない時にクライアントを実行してしまったら、どうなるんでしょうか?
![]()
【Yuki】
良い質問ですね...。その場合は、接続先が見つからないというエラー(ConnectionRefusedError)が発生して、プログラムが止まってしまいます。
実際の開発では、ネットワークが不安定だったり、相手の応答が遅かったりすることも多いので、「例外処理」と「タイムアウト」を設定しておくのが望ましいです。
import socket
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# 5秒間応答がなければ諦める設定
s.settimeout(5.0)
s.connect(('127.0.0.1', 50000))
# ...通信処理...
except socket.timeout:
print("タイムアウトしました。接続に時間がかかりすぎています。")
except ConnectionRefusedError:
print("サーバーに接続できませんでした。起動しているか確認してください。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
![]()
【Yuki】
こうやってエラーを想定して書いておくと、より「堅牢な」プログラムになりますね。...あ、堅牢というのは、壊れにくいという意味ですよ。
最新のAI技術とネットワークの関係
![]()
【Hiroki】
ソケット通信って、なんだかすごく原始的な感じがしますが、最近のAI技術とかでも使われているんですか?
![]()
【Yuki】
実は、とても密接に関わっているんですよ。
最近のAI、例えばGoogleのGeminiのようなモデルを使う際、私たちはライブラリを通じてAPIにリクエストを送ります。そのライブラリの内部でも、最終的にはこのようなソケット通信の仕組みが動いているんです。
現在、最新のAIを操作するためのライブラリとして google-genai が登場しています。これを使って gemini-3-flash-preview(※最新モデルの例)などのモデルと対話する際も、背後ではHTTPというプロトコルが使われ、さらにその下層ではTCPソケットがデータの運び役を担っています。
![]()
【Hiroki】
僕たちが便利なライブラリを使ってAIと会話できるのも、このソケット通信という土台があるからなんですね。
![]()
【Yuki】
そうなんです...。高機能なツールも、元を辿ればこうした小さな通信の積み重ねでできていると思うと、なんだか感慨深いですよね。
自分の書いた小さなツールが、誰かのネットワークの一部になる...。ソケット通信を学ぶことは、インターネットの構造そのものを理解することに繋がると思います。
発展:ノンブロッキング通信と多重化
![]()
【Hiroki】
今のサーバーのコードだと、1人のクライアントと通信している間、他の人は接続できないんですよね?
![]()
【Yuki】
はい、よく気づきましたね。今のコードは「ブロッキング」という方式で、一つの処理が終わるまで次へ進めません。
これを解決するために、複数の接続を同時に扱う「並行処理」が必要になります。Pythonでは threading モジュールを使って、新しい接続が来るたびに新しいスレッド(処理の分身のようなもの)を作る方法が一般的です。
もっと高度な方法だと、asyncio というライブラリを使って、非同期に大量の通信をさばくこともできます。将来、もっとたくさんのデータを扱いたくなったら、ぜひ調べてみてくださいね。
まとめ
![]()
【Yuki】
今日は、Pythonでのソケット通信の基礎を学びました。
- ソケットはネットワーク通信の窓口。
- IPアドレスで住所を、ポート番号で窓口を指定する。
- TCPは信頼性重視、UDPは速度重視。
- Pythonの
socketライブラリで、サーバーとクライアントを実装できる。 - 通信データはバイト形式で送受信するため、エンコードとデコードが必要。
![]()
【Hiroki】
基礎的なことですが、一つ一つの手順に意味があることがよく分かりました。Yukiさん、丁寧に教えてくれてありがとうございました!
![]()
【Yuki】
いえいえ...。Hirokiくんが一生懸命聞いてくれたので、私も説明しやすかったです。
もし興味が湧いたら、今度はサーバーから複数のクライアントにメッセージを送るチャットプログラムなんかに挑戦してみると楽しいかもしれません。
ネットワークの世界はとても広いですが、まずはここから一歩ずつ進んでいきましょう。
情報の根拠・参考サイト: - socket — 低レベルネットワークインターフェース - Python でのネットワークプログラミング(英語) - google-genai ライブラリ ドキュメント
「ソケット通信」のサンプルコードを見る
この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。
「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。
- 専門家の知見に基づいた、保守性の高いコード設計
- AIの専門家による、Gemini API等の最新AIを組み合わせた高度な自動化
- ChatGPT等が生成したコードのデバッグ・最適化
「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。


