前提、していること
Pythonで、socketモジュールを使って、TCPソケット通信のプログラムを書いています。
試作的にローカルでサーバとクライアントをつくり、動きを確認してみています。
TCPコネクションを2つ張っておいています。
処理の概要は下記です。
1、クライアントからサーバにsend
2、サーバでrecv
3、サーバからクライアントにsend ※2つのソケットのうち、どちらで送るかは乱数生成により不確実
4、クライアントでrecv
最後の4の動きで理解できない現象となっております。
実行時のコンソール表示
####client_socket1からsendしたとき(条件分岐でいうとran==1のとき)
C:\Users\ユーザー名\PycharmProjects\practiceProject\venv\Scripts\python.exe C:/Users/ユーザー名/PycharmProjects/practiceProject/server.py ranの値:1 1回目 Traceback (most recent call last): File "C:/Users/ユーザー名/PycharmProjects/practiceProject/server.py", line 40, in <module> client_socket1.send(bytes('Yes', 'utf-8')) ConnectionAbortedError: [WinError 10053] 確立された接続がホスト コンピューターのソウトウェアによって中止されました。 test 2回目 0Byteで受信した 3回目 0Byteで受信した プロセスは終了コード 1 で完了しました
C:\Users\ユーザー名\PycharmProjects\practiceProject\venv\Scripts\python.exe C:/Users/ユーザー名/PycharmProjects/practiceProject/client.py sc1で受信した Yes close プロセスは終了コード 0 で完了しました
####client_socket2からsendしたとき(条件分岐でいうとran==2のとき)
C:\Users\ユーザー名\PycharmProjects\practiceProject\venv\Scripts\python.exe C:/Users/ユーザー名/PycharmProjects/practiceProject/server.py ranの値:2 1回目 test 2回目 タイムアウトになった プロセスは終了コード 0 で完了しました
C:\Users\ユーザー名\PycharmProjects\practiceProject\venv\Scripts\python.exe C:/Users/ユーザー名/PycharmProjects/practiceProject/client.py タイムアウトになった sc2で受信した No close プロセスは終了コード 0 で完了しました
疑問に思っていること
サーバからクライアントに対し、
client_socket1からsendした場合は、サーバの2回目のdata = client_socket2.recv(1024)で0バイトが返ってきています。これはつまり、クライアント側の接続が切断されている、ということのはずです。
一方で、
client_socket2からsendした場合は、サーバの2回目のdata = client_socket2.recv(1024)でタイムアウトエラーになっています。つまり、クライアント側の接続は切断されていないということだと思います。
この違いの理由、原因は何なのでしょうか?
クライアント側ではfinalyでcloseしているので、必ず接続が切断され、サーバ側のrecvの戻り値としては必ず0バイトが返ってくるのが正しいのでは?と思っています。
該当のソースコード
Pycharmなどにこのまま張り付けて実証動作可能です。
####server.py
Python
1import socket 2import random 3 4sc1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 5sc2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 6 7# ポート10000を割り当てる 8sc1.bind((socket.gethostname(), 10000)) 9# ポート10001を割り当てる 10sc2.bind((socket.gethostname(), 10001)) 11 12sc1.listen(5) 13sc2.listen(5) 14 15client_socket1, address1 = sc1.accept() 16client_socket2, address2 = sc2.accept() 17 18client_socket1.settimeout(3) 19client_socket2.settimeout(3) 20 21i = 0 22 23# テキトーに分岐させるために乱数生成 24ran = random.randint(1, 2) 25print("ranの値", end=':') 26print(ran) 27 28while True: 29 i = i + 1 30 print(str(i) + '回目') 31 try: 32 data = client_socket2.recv(1024) 33 print(data.decode('utf-8')) 34 if not data: 35 print('0Byteで受信した') 36 except socket.timeout as toe: 37 print('タイムアウトになった') 38 break 39 40 if ran == 1: 41 client_socket1.send(bytes('Yes', 'utf-8')) 42 else: 43 client_socket2.send(bytes('No', 'utf-8')) 44 45client_socket1.close() 46client_socket2.close() 47 48
####client.py
Python
1import socket 2 3sc1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4sc2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 5 6sc1.settimeout(3) 7sc2.settimeout(3) 8 9sc1.connect((socket.gethostname(), 10000)) 10sc2.connect((socket.gethostname(), 10001)) 11 12sc2.send(bytes('test', 'utf-8')) 13 14try: 15 msg = sc1.recv(1024) 16 print('sc1で受信した') 17 print(msg.decode('utf-8')) 18except socket.timeout as toe: 19 print('タイムアウトになった') 20 try: 21 msg = sc2.recv(1024) 22 print('sc2で受信した') 23 print(msg.decode('utf-8')) 24 except socket.timeout as toe: 25 print('応答なし') 26finally: 27 print('close') 28 sc1.close() 29 sc2.close()
###補足情報(FW/ツールのバージョンなど)
Python3.8くらい
Pycharm
よろしくお願い致します。
あなたの回答
tips
プレビュー