0

各クライアントが 3 つのスレッドを作成し、複数のクライアントが一度に接続できる、かなり基本的なクライアント/サーバー コードがあるとします。サーバーに着信接続を待機させ、接続の取得を開始したら、実行中のスレッドがなくなるまで実行してから終了します。コードは以下のようになります。(つまり、サーバーが「永久に機能する」のではなく、すべてのスレッドが終了したらサーバーを終了させたい)。

編集:サーバーが着信接続を待機するようにします。接続が開始されると、実行中のスレッドがなくなるまで接続を受け入れ続け、終了します。これらの接続はやや散発的です。

import socket
import threading

# Our thread class:
class ClientThread ( threading.Thread ):

   # Override Thread's __init__ method to accept the parameters needed:
   def __init__ ( self, channel, details ):

      self.channel = channel
      self.details = details
      threading.Thread.__init__ ( self )

   def run ( self ):

      print 'Received connection:', self.details [ 0 ]
      self.channel.send ( 'hello from server' )
      for x in xrange ( 10 ):
         print self.channel.recv ( 1024 )
      self.channel.close()
      print 'Closed connection:', self.details [ 0 ]

# Set up the server:
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 2727 ) )
server.listen ( 5 )

# Have the server serve "forever":
while True:
   channel, details = server.accept()
   ClientThread ( channel, details ).start()
4

2 に答える 2

1

あなたのコメントによると、あなたが探しているのは、サーバーへの最初の接続が確立された後に接続のカウントを開始し、既存の接続がなくなったらサーバーを強制終了することです。

現在の無限 while ループの差し迫った問題は、 each のブロックaccept()です。したがって、何があっても、常に別の接続を待っています。そのループから抜け出すには、他のスレッドから中断する必要があります。しかし、別の解決策はイベント ループを大きくすることであり、新しい接続を受け入れる行為はその一部にすぎません。ループは、終了する条件もチェックする必要があります。

この例は、可能な方法の 1 つにすぎません。Queue.Queueを使用して、作業カウンターを調整します。

import socket
import threading
import select
from Queue import Queue

class ClientThread ( threading.Thread ):

   def __init__ ( self, channel, details, queue=None ):
      self.channel = channel
      self.details = details
      self.queue = queue
      threading.Thread.__init__ ( self )

   def run ( self ):

      if self.queue:
         self.queue.put(1)

      print 'Received connection:', self.details [ 0 ]
      self.channel.send ( 'hello from server' )
      for x in xrange ( 10 ):
         print self.channel.recv ( 1024 )
      self.channel.close()
      print 'Closed connection:', self.details [ 0 ]

      if self.queue:
         self.queue.get_nowait()

# Set up the server:
server = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
server.bind ( ( '', 2727 ) )
server.listen ( 5 )

rlist = [server]
work_queue = Queue()

def accept_client():
   channel, details = server.accept()
   ClientThread ( channel, details, work_queue ).start() 

accept_client()

while not work_queue.empty():
   server_ready, _, _ = select.select(rlist,[],[], .25)
   if server in server_ready:
      accept_client()

print "Shutting down"
server.close()
print "Exiting"

サーバーソケットでのアクティビティを検出する簡単な方法としてselect.selectを使用しますが、タイムアウトも使用します。サーバーの準備ができたら、新しい接続を受け入れます。.252 番目のタイムアウトに達すると、再びループして待機します。

キューを作成し、それが空かどうかを常にチェックしていることがわかります。キューは各スレッドに渡されます。スレッドが開始されると、いくつかの作業がキューに記録されます。データは任意です。ただの旗。スレッドが完了すると、その項目がキューからクリアされます。その結果、最初の接続が受信された後、キューは空ではなくなり、ループが実行され続けます。いずれかの時点で (現在のすべてのスレッドが終了したために) キューが空になると、ループが中断され、サーバーがシャットダウンされます。

于 2012-06-14T17:53:42.823 に答える
0

ループbreakから抜けた場合、プロセスはすべて終了するまで待機し、その後終了します。whileClientThreads

クライアントスレッドは非デーモンであるため、これは機能します。詳細についてthreading.Thread.daemonは、 を参照してください。

于 2012-06-14T14:45:00.700 に答える