Loading
BLOG 開発者ブログ

2022年12月4日

【Python】ソケット通信をやってみる!

今回はPythonを使用したTCP Socket通信の入門的な内容に取り組んでみたいと思います。

Webやモバイルなど、普段アプリケーションの開発をしていると何気なくHTTPによる通信をしています。
ただ、そういった通信の仕組みをただ使用しているだけだと、どうやって動いているのかなど深い理解にはなかなか及びずらいと思います。
そんなわけで今回はソケット通信に取り組むことで、ちょっとだけ理解を深めていければと思います。

目次


はじめに

こんにちは。
クラウドソリューショングループのimai.kです。


この記事は アイソルート Advent Calendar 2022 の4日目の記事です。
昨日は namiki.t さんの iOS Safari で常にスクロールバーを表示する でした。ぜひこちらもご覧ください。

やりたいこと

今回やりたいことは、ローカル上でTCPサーバー・クライアントを動作させてソケット通信を行うことです。
言語はPythonを使用します。なお、Pythonのバージョンは3系を前提としています。

実際のコード

というわけで、早速サーバー・クライアントのソースコードを作成すると以下のようになります。

↓サーバー側

# -*- coding : UTF-8 -*-

import socket

server_ip = socket.gethostbyname(socket.gethostname())
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp_server.bind((server_ip, 52001))

tcp_server.listen(1)
print('Wait tcp accepting...')
client, address = tcp_server.accept()
print('Connected client ip : {}'.format(address))

rcv_data = client.recv(1024)
print('Data : {}'.format(rcv_data.decode("utf-8")))

client.send('Hi!'.encode("utf-8"))
client.close()

↓クライアント側

# -*- coding : UTF-8 -*-

import socket

ip_address = socket.gethostbyname(socket.gethostname())
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_socket.connect((str(ip_address), 52001))

tcp_socket.send('Hello!'.encode("utf-8"))
response = tcp_socket.recv(1024)
print('Data : {}'.format(response.decode("utf-8")))

動かしてみる

では、作成したコードを動かしてみます。

まずはサーバー側のコードを以下の要領で実行します。

$ python3 tcp-server.py

次にクライアント側を実行します。

$ python3 tcp-client.py

それぞれ、以下のように出力されればOKです。

↓サーバー側

↓クライアント側

また、実際にどんなパケットが流れているのか、キャプチャーしてみましょう。
以下はWiresharkを使用してパケットキャプチャーしたときのスクリーンショットです。

今回のソケット通信はTCPを使用してコネクションを確立していますが、
TCPコネクションはいわゆる3ウェイハンドシェイクという接続を行います。

画像を見ると、SYN・ACK・FINといったキーワードが現れていますが、なんとなくコネクションの確立→メッセージの送受信→コネクションのクローズといった流れが見えますね。
(なお、今回はTCPコネクションを深掘りした話はいたしません)

やってみて得られたこと

上記で作成したコードは、サーバーとクライアントが一つのメッセージを送受信する、というとてもシンプルなものですが、
やってみた感想は、比較的低レイヤーなことながらもメッセージの送受信がこんな簡単にできてしまうんだ、というものでした。

また、普段使用しているHTTP通信でも、裏では上記同様のTCPコネクションが確立された上で通信が行われています。
少し低レイヤーなことを行うと、そういった流れがより直感的に理解しやすくなるため面白いですね。

今回は、かなりシンプルかつ初歩的なことしかしていませんが、通信をより適切に制御するには、サーバーソケットをスレッド化し、複数のクライアントからの接続を待ち受けられるようにするなど色々改良すべき点はあります。
そういったことも今度試してみたいと思います。

明日は anan さんの 迷えるエンジニアへ贈る、キャリア形成のために必要なたった一つのルール です。



imai.kのブログ