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

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

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

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

Python

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

Q&A

解決済

1回答

1340閲覧

Pythonでソケット通信。異なるポートからの応答を受信したい。

circular2016

総合スコア52

Socket.IO

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

Python

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

0グッド

0クリップ

投稿2021/08/16 13:48

編集2021/08/17 03:16

前提・実現したいこと

前提
外部装置とソケット通信するインタフェースがあります。
応答内容によって応答が送られてくるポート番号が違います。
正常系の場合と異常系の場合で異なるのですが、当然、どちら経由で送られてくるかはわからないので、両方受信できるようにする必要があります。

Pythonでsocketモジュールを使って実装をしようとしています。
二つのポート番号からの受信を受け付けるようにしたいです。

考えているコード

まず、ポート番号が異なるので、ソケットオブジェクトは必ず2つ生成しておく必要があると認識しています。
その上で、
data1 = socket1.recv(1024)
data2 = socket2.recv(1024)
を同時に行うと、必ずタイムアウトエラーになってしまうので、
下記のように、正常系でタイムアウトになったら異常系のポートを見に行こうと考えています。

一応、動作することは確認できました。

Python

1import socket 2 3# 正常系応答が返ってくる用のポート 4socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 5socket1.settimeout(3) 6socket1.connect((socket.gethostname(), 10000)) 7 8# 異常系応答が返ってくる用のポート 9socket2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10socket2.settimeout(3) 11socket2.connect((socket.gethostname(), 10001)) 12 13try: 14 data = socket1.recv(1024) 15 print('正常系の応答で返ってきた') 16except socket.timeout as toe: 17 try: 18 data = socket2.recv(1024) 19 print('異常系の応答で返ってきた') 20 except socket.timeout as toe: 21 print('正常でも異常でもない。応答なし') 22 23

質問したい点

上記のように、タイムアウトエラーを契機として見る先を切り替えるしかないでしょうか?
ただ、これだとタイムアウト値でかなり性能が左右されるので、最善の策ではない気がしています。
しかし、代わる方法もわかりません。
何か良い方法はありませんでしょうか?

補足情報(FW/ツールのバージョンなど)

Pycharm
Python3.8くらい
フレームワークは未使用

ソケット通信の実装で主に参考にしたサイト:https://dev.classmethod.jp/articles/python3socketserver/

【追記修正】
情報不足で申し訳ありません。

通信の流れとしては、
①クライアント→サーバ(外部装置)にsend(ポートは固定)
②サーバでrecvして内容を解析。
③サーバ→クライアントにsend
(内容によってポートが2分岐するので不定)
④クライアントでrecv
という流れです。

④の実現方法を質問したかったです。
待ち受ける、というのはおそらく正しくない表現で、クライアントでrecvしたい、という意味でした。

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

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

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

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

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

guest

回答1

0

ベストアンサー

文章では「待ち受ける」「受け付ける」と書いてあるので、TCPサーバープログラムを作るのかと思ったのですが、コードを見るとconnectを使っているので、TCPクライアントを作るのでしょうか?

日本語が間違っていて、クライアントを作るのであれば、
どちらのポートで待ち受けているか分からないサーバーにクライアントとして接続しに行くので有れば、その方法しか無いので、スレッドを分けてそれぞれで接続に行くくらいでしょうか。

それとも日本語が正しい場合は、connectじゃなくてbindlistenで同時に2つのポートで待ち受けられます。

#追記
クライアントから、サーバーにあらかじめTCPコネクションを2つ張っておいて、
両方のコネクションを同時に受信チェックしたいということのようですね。

selectを使って入力のあるソケットを教えてもらうのが簡単です。

Python

1import select 2 3socks = select.select([socket1,socket2],[],[])[0]: 4for sock in socks: 5 data = sock.recv(1024) 6 print(f"ポート {sock.getsockname()[1]} から返ってきた")

必要に応じて、第4引数でタイムアウト値を指定して下さい。タイムアウト時はsocksが空リストになります。

投稿2021/08/16 14:16

編集2021/08/17 03:55
otn

総合スコア84498

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

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

circular2016

2021/08/17 03:18

回答ありがとうございます。 記載不足で申し訳ありません。 質問内容を追記修正致しました。 クライアントを作りたいと思っています。
otn

2021/08/17 03:22

クライアントから、サーバーにあらかじめTCPコネクションを2つ張っておいて、 両方のコネクションを同時に受信チェックしたいということでしょうか?
circular2016

2021/08/18 15:27

反応が遅くなり、申し訳ありません。 クライアントから、サーバーにあらかじめTCPコネクションを2つ張っておいて、 両方のコネクションを同時に受信チェックしたい →そうです、その通りです。 selectモジュールというのがあるのですね。 シングルスレッドで複数のソケットの受信チェックできるものと認識しました。 教えて頂いたものでなんとかできそうです。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問