質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

2858閲覧

Pythonのsocketモジュール_recvでタイムアウトエラーになる場合と0Byteで返ってくる場合の違いがわかりません

circular2016

総合スコア52

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/08/18 19:14

前提、していること

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

よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問