2016-10-13 11 views
1

私はPythonの初心者です。そして、同じネットワークからのリクエストを処理するリスナ/サーバを作成する必要があります。だから私はsocketを使用しています。私はクライアントからリクエストjsonを取得し、サーバー/リスナーは処理して結果を返します。それはすべて起こりそうなことです。そして、サーバーとクライアントの間で前後の通信はありません。複数の着信要求を処理するマルチスレッド

コードは次のようになります。

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
server_address = ('localhost', 10000)    
sock.bind(server_address)  
sock.listen(1) 

while True: 
    connection, client_address = sock.accept() 

    while True: 
     #read request data 
     #process request 
     #reply response to **connection** object 
     break #continue waiting for new request 

今問題現在のリクエストの処理が完了するまで、サーバは新しい要求を受け入れないだろうということです。どういうわけか、処理を実行して、別の同時スレッドで応答返信を送信する必要があります。私は処理ロジックを別のクラスRequestHandlerThreadクラスに拡張してカプセル化しました。 connectionオブジェクトを私のカスタムクラスRequestHandlerのインスタンスに渡しました。私はこのようなものでした :私は立ち往生しているところが、ここで

requestHandler = RequestHandler(deepcopy(connection)) 
requestHandler.daemon = True 
requestHandler.start() 

です。新しいリクエストを受信するたびに、同じconnectionオブジェクトを新しいインスタンスRequestHandlerに渡すことはできますか?上のコードのようにディープコピーすると、次のエラーが表示されます。

TypeError: Cannot serialize socket object 

私は何か絶対に間違っていますか?私はいくつかの異なるアプローチに従うべきですか?

答えて

1

Threadクラスを拡張する必要はありません。最も単純版のこのです:

import threading 

def client_handler(connection): 
    #read request data 
    #process request 
    #reply response to **connection** object 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
server_address = ('localhost', 10000)    
sock.bind(server_address)  
sock.listen(1) 

while True: 
    connection, client_address = sock.accept() 
    threading.Thread(target=client_handler, args=(connection,)).start() 

今、あなたは、あなたが望むなら、それは大丈夫ですRequestHandlerクラスにあなたのソケットオブジェクトをラップすることがあります。しかし、ソケットをコピーすることはできません。代わりに参照を渡してください:RequestHandler(connection)。とにかくそれをコピーするのはなぜですか?

コピー可能でないのは、それが何らかのシステムリソース(つまりソケット)を表しているからです。同じリソースを指す2つのオブジェクトがある場合、それらは互いに競合します。また、Cレベルでは、複数の所有者が存在する場合、純粋なファイル記述子(ソケットは単純にCレベルの数値)を同期するのは非常に難しいです。したがって、ソケットオブジェクトは、基礎となるファイル記述子に対する一意の「ゲートウェイ」の一種です。

+0

**(1)**コピーしないと、複数の着信要求を受け入れることができますか? 'connection'オブジェクト参照をあるスレッドに渡し、' connection、client_address = sock.accept() '行の' connection'変数に新しいインスタンスを割り当てる別の要求が来たらどうなりますか? **(2)**着信要求ごとに新しい接続オブジェクトを作成しますか? **(3)**スレッドクラスの拡張アプローチもうまく動作しますか?私は 'target = client_handler'が内部的に同じことをすると思いますか? – Mahesha999

+0

@ Mahesha999 1)Pythonの変数はポインタ(または参照)です。 'connection、client_address = sock.accept()'を実行すると、オブジェクトはコピーも変更もしません。新しいソケットオブジェクトを古い 'connection'変数に割り当てます。しかし、古い 'connection' **オブジェクト**はまったく影響を受けません。 – freakish

+0

2)いいえ。新しい**接続された**クライアントごとに新しい接続オブジェクトが存在します。一般的に、クライアントとサーバーは、この「取引」を行います。「今、私はこのパイプ上であなたと接続しています。 1つのクライアントが複数の要求を発行することがあります。あなたの場合は、最初のリクエストの後に接続を閉じたいと思うかもしれませんが。あなたのケースでは答えはイエスです。 3)はい、うまくいくでしょう。それをする必要はないということだけです。 – freakish

関連する問題