python で tcp 接続(server/client)でメッセージ送受信する
2024/01/16 00:00:00
前提 #
- windows10 git-bash 環境でpyenvが動作する環境
- 作成したソース一式は以下に登録済み
https://github.com/oya3/pystream
作成手順 #
python 3.11.6 環境構築 #
# 作業エリア pystream 作成
$ mkdir pystream
$ cd pystream
$ pyenv local 3.11.6
$ python -V
3.11.6
$ python -m venv venv
$ source venv/Scripts/activate
# yaml ファイル制御用パッケージ
$ pip install pyyaml
...
[notice] A new release of pip is available: 23.2.1 -> 23.3.2 # <--- 新しいpipがあるといってる
[notice] To update, run: python.exe -m pip install --upgrade pip
# pip 更新
$ python.exe -m pip install --upgrade pip
# exe 化用パッケージ
$ pip install pyinstaller
$ pip freeze > requirements.txt
# エディタで静的解析が必要な場合(poetry使わないと開発用パッケージが混ざるので注意)
$ pip install jedi flake8 importmagic autopep8 yapf black
tcp server 作成 #
サーバ情報(ip,port)を外部ファイル(yaml)に記載して、その内容でtcp server を起動するサンプル
動作内容は以下の通り。
- クライアントから接続があるまで無限待ち
- クライアント接続後、メッセージ受信待ち
- メッセージ受信後、メッセージ内容をクライアントにオウム返し
$ emacs server.py
1import socket
2import argparse
3import traceback
4import yaml
5
6
7def main(config):
8 server_ip = str(config['ip'])
9 server_port = int(config['port'])
10 listen_num = 5
11 buffer_size = 4096
12 # 1.ソケットオブジェクトの作成
13 tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
14 # 2.作成したソケットオブジェクトにIPアドレスとポートを紐づける
15 tcp_server.bind((server_ip, server_port))
16 # 3.作成したオブジェクトを接続可能状態にする
17 tcp_server.listen(listen_num)
18 print("server {}:{}".format(server_ip, server_port))
19 # 4.ループして接続を待ち続ける
20 while True:
21 # 5.クライアントと接続する
22 client, address = tcp_server.accept()
23 print("[*] Connected!! [ Source : {}]".format(address))
24 # 6.データを受信する
25 data = client.recv(buffer_size)
26 print("[*] Received Data : {}".format(data.decode()))
27 # 7.クライアントへデータを返す
28 message = "ACK!! [{}]".format(data.decode())
29 client.send(message.encode())
30 # 8.接続を終了させる
31 client.close()
32
33
34def read_config(args):
35 config_file = 'server.yaml'
36 if args.config:
37 config_file = args.config
38 with open(config_file, 'r') as yml:
39 config = yaml.safe_load(yml)
40 return config
41
42
43if __name__ == '__main__':
44 try:
45 # 入力引数設定
46 parser = argparse.ArgumentParser(description='tcp server')
47 parser.add_argument('-c', '--config') # option: config ファイル指定
48 args = parser.parse_args() # 入力引数取得
49 config = read_config(args)
50 main(config)
51 except Exception: # # main() で発生する異常はすべてキャッチする
52 t = traceback.format_exc()
53 print("ERROR: {}".format(t))
サーバのIPアドレスとポート番号をyamlファイルに記載
とりあえず、127.0.0.1:9901(ローカルホスト)にしておく
$ emacs server.yaml
1ip: "127.0.0.1"
2port: 9901
tcp client 作成 #
指定したip,portにメッセージを送信するサンプル
内容は以下の通り
- 入力引数にip,port,messageを指定
- 入力引数に従いtcp client作成しmessageを送信
- 送信完了後、受信待ちをする
- 受信すると、送信したmessageと同じ内容が返される
$ emacs client.py
1import socket
2import argparse
3import traceback
4
5
6def main(args):
7 target_ip = str(args.ip) # "127.0.0.1"
8 target_port = int(args.port) # 8080
9 buffer_size = 4096
10 # 1.ソケットオブジェクトの作成
11 tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
12 # 2.サーバに接続
13 tcp_client.connect((target_ip, target_port))
14 # 3.サーバにデータを送信
15 tcp_client.send(str(args.message).encode())
16 # 4.サーバからのレスポンスを受信
17 response = tcp_client.recv(buffer_size)
18 print("[*]Received a response : {}".format(response.decode()))
19
20
21if __name__ == '__main__':
22 try:
23 # 入力引数設定
24 parser = argparse.ArgumentParser(description='tcp client')
25 parser.add_argument('ip', help='ip')
26 parser.add_argument('port', help='port')
27 parser.add_argument('message', help='message')
28 args = parser.parse_args() # 入力引数取得
29 main(args)
30 except Exception: # # main() で発生する異常はすべてキャッチする
31 t = traceback.format_exc()
32 print("ERROR: {}".format(t))
exe化 バッチ 作成&実行 #
以下をバッチを実行すると dist ディレクトリにexeファイルが作成される
$ emacs server-build.bat
1pyinstaller server.py --onefile
$ emacs client-build.bat
1pyinstaller client.py --onefile
$ emacs build.bat
1call server-build.bat
2call client-build.bat
exe 化する
distディレクトリにそれぞれ、server.exe, client.exe が生成される
$ ./build.bat
実行手順 #
exe を利用する場合 #
server 起動
server.yaml は自分の設定に置き換えておく必要がある。localhostのままでもいいがserver,clientは同じ端末で実施する必要がある
※ server.exeをダブルクリックで起動しても server.exe 直下の server.yaml を読み込んで実行するようになっている
# server.yaml を適宜記載しておくこと
$ cd pystream
$ cd dist
# パターン1:暗黙で同じ階層のserver.yamlを読み込んで起動
$ ./server.exe
# パターン2:-c 省略オプションで指定したserver.yamlを読み込んで起動
$ ./server.exe -c server.yaml
# パターン3:--config オプションで指定したserver.yamlを読み込んで起動
$ ./server.exe --config server.yaml
client 起動
server.yaml の内容のip,portを指定してメッセージ送信する
$ cd pystream
$ cd dist
$ ./client.exe 127.0.0.1 9901 test
python を利用する場合 #
準備
# for git-bash
$ cd pystream
$ python -m venv venv
$ source venv/Scripts/activate
$ pip install -r requirements.txt
server 起動
$ python server.py
$ python server.py -c server.yaml
client 起動
server.yaml の内容のip,portを指定してメッセージ送信する
$ python client.py 127.0.0.1 9901 test
参考URL #
- PythonでTCP通信(サーバ編)
https://qiita.com/keiusukematsuda/items/aacded313fdb6c08f410 - PythonでTCP通信(クライアント編)
https://qiita.com/keiusukematsuda/items/362450fda4beca76c030 - ArgumentParserの使い方を簡単にまとめた
https://qiita.com/kzkadc/items/e4fc7bc9c003de1eb6d0