2013-05-24 8 views
6

ネットワーク通信用のソケットについて学ぶときに問題があります。私は接続を聞き、クライアント接続のためのプロセスを作成する単純なスレッドを作ったが、私の問題はsocket.accept()を取り消す方法を見つけられなかったのでスレッドを正しく結合できないことであるいつ私がプログラムを終了したい。ファイアウォールスレッドのリスニングソケットを閉じる

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

class ServerThread(threading.Thread): 

    def __init__(self, queue, host, port): 
     threading.Thread.__init__(self) 
     self.queue = queue 
     self.running = True 
     self.hostname = host 
     self.port = port 

    def run(self): 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.socket.bind((self.hostname, self.port)) 
     self.socket.listen(1) 
     while self.running: 
      try: 
       conn, address = self.socket.accept() 
       process = Process(target=server_slave, args=(conn, address, self.queue)) 
       process.daemon = True 
       process.start() 
      except socket.timeout: 
       pass 

    def stop(self): 
     self.running = False 
     self.socket.close() 

私はself.setDaemon(True)を設定し、ちょうど偉大なガベージコレクタにすべてを手渡し、メインプログラムを終了することで閉じるようにプログラムを得るために管理している - それは悪い解決策のように思えます。私もソケットのタイムアウトを設定しようとしましたが、その結果は[Errno 35] Resource temporarily unavailableになります(実際のタイムアウトに関係なく、何年に設定しても...)。

私は間違っていますか?私はスレッドを愚かな方法で設計したのですか、接続を受け入れることについて何か忘れたことがありますか?

+0

conn.settimeout(None)を入れて 'それは悪い解決策のように思える' - それは動作しますか? OSがすべてのスレッドを終了させるのが気に入らなければ、メインスレッドまたは他のスレッドからリスニングソケットを閉じることができます。これは通常、accept()がエラーを伴って 'early'を返すようにします。ほとんどのOS /言語で動作しますが、Pythonで試したわけではありませんので、答えはありません。 –

+0

これは機能しますが、私は潜在的なクライアントをそれほどうまく扱っていないかもしれないと感じています。コードを完成させるためにはより良いソリューションを投稿しましたが、すぐに参加しなければならない新しいプロセスを作成することで終わってしまったので、少し奇妙に見えます。 – Norling

答えて

8

スレッドを閉じるための1つの方法は、ソケットへの接続を作成し、スレッドを完了させることです。

def stop(self): 
    self.running = False 
    socket.socket(socket.AF_INET, 
        socket.SOCK_STREAM).connect((self.hostname, self.port)) 
    self.socket.close() 

これは動作しますが、それは最適ではない可能性がありますように、それはまだ感じている...

+0

はい - 「人工的に」待機条件を満たす(ここでは一時的なローカル接続を開くように)、トリックの「ブロックされたスレッドを停止」バッグにもあります。 –

+0

あなたはこのことを知っているようです! ^^ 助けてくれてありがとう!私が試してみてください他のトリックですか? – Norling

+0

現在、この問題/コードを理解しようとしていますが、私は同じことをやったでしょうが、 "socket、。socket(socket.AF_INET ...)行の周りに頭を浮かべることはできません - 目的は何ですか? – Kev1n91

0

ほとんどのケースでは、一度接続が受け入れられる新しいスレッドやプロセスを開きます。接続を閉じるには、whileループを解除します。ガベージコレクションはスレッドまたはプロセスを削除しますが、参加することで後で取り残されることはありません。

永続ソケットは、ユーザーが閉じたりタイムアウトすると閉じます。静的なWebページのような非永続的な情報は、情報を送信した後に終了します。

これは、Pythonの永続ソケットサーバの良い例です。マルチプロセッシングを使用しています。つまり、CPUに依存するタスクのために複数のコアで実行できます。より一般的にはマルチスレッドと呼ばれます。

import socket 
import multiprocessing 

def run(): 
    host = '000.000.000.000' 
    port = 1212 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind(('', port)) 
    sock.listen(3) 
    while True: 
     p = multiprocessing.Process(target=worker, args=sock.accept()).start() 
def worker(conn, addr): 
    while True: 
     if data == '': 
      #remote connection closed 
      break 
     if len(dataList) > 2: 
      # do stuff 
      print 'This code is untested' 

run() 
-1

部分的にテスト済みのソリューション

  1. は右while
  2. self.socket.settimeout(0.1)を入れて右accept
+4

このアドバイスに従うことは、私が一日中作った最悪の決定でした。 – Paradoxis

+0

私は 'settimeout()'が私のために働くことを発見しました。http://stackoverflow.com/a/41643863/143931を参照してください。 – fuenfundachtzig

関連する問題