2013-05-24 19 views
6

Ağ iletişimi için yuvalar hakkında bilgi edinmek için bir sorunum var. Bağlantıları dinleyen ve istemcileri bağlamaya yönelik süreçler oluşturan basit bir iş parçacığı yaptım, sorunum olsa da, socket.accept() - çağrıyı iptal etmenin bir yolunu bulamadığım için iş parçacığının düzgün bir şekilde katılmasını sağlayamam. programdan çıkmak istediğimde.Dinleme soketini python iş parçacığındaki kapatın

Kodum şunun gibi görünüyor;

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() 

Ben self.setDaemon(True) ayarlama ve sadece büyük çöpçüyle şeyi teslim, ana programdan çıkmadan kapatmak için programı almak başarmış - ama bu kötü bir çözüm gibi görünüyor. Ayrıca soket için bir zaman aşımı ayarlamayı denedim, ancak bu, [Errno 35] Resource temporarily unavailable almamın sonucudur (gerçek zaman aşımından bağımsız olarak, yıllara ayarladığım zaman bile ...).

Neyi yanlış yapıyorum? İpliği aptalca tasarlamış mıyım yoksa bağlantıları kabul etmekle ilgili bir şey özledim mi?

+0

sonra sağ conn.settimeout(None) koyun while

  • önce self.socket.settimeout(0.1) Put 'ama bu kötü bir çözüm gibi görünüyor' Kısmen test - çalışır? İşletim Sisteminin tüm iş parçacıklarını sonlandırmasını istemiyorsanız, dinleme soketini ana veya diğer iş parçacığından kapatmayı deneyebilirsiniz. Bu genellikle accept() 'hata' ile 'erken' döndürmesine neden olur. Çoğu OS/dil üzerinde çalışır, ancak Python ile denemediğinden, bir yanıt vermez. –

  • +0

    Çalışıyor - ama potansiyel müşterilere bunu yapmama konusunda çok iyi davranamadığımı hissediyorum. Kodun tamamlanmasına izin verdiği ölçüde daha güzel görünen bir çözüm gönderdim, ancak hemen katılmam gerekecek yeni bir süreç oluşturarak bitmesi garip görünüyor. – Norling

    cevap

    8

    İş parçacığının kapanmasını sağlamanın bir yolu sokete bağlantı yapmak gibi görünüyor, böylece iş parçacığı tamamlanmaya devam ediyor.

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

    Bu çalışır, ancak en uygun olmayabilir gibi hala hissediyor ...

    +0

    Evet - 'yapay olarak' bekleme koşulunu karşılayan, (burada geçici bir yerel bağlantıyı açarken olduğu gibi), aynı zamanda 'engellenen engelleme' püf noktası olan çantada. –

    +0

    Bu şeyi biliyor gibisin! ^^ Yardımın için teşekkürler! Denediğim başka numaralar var mı? – Norling

    +0

    Şu anda bu sorunu/kodu anlamaya çalışıyordum - Ben de aynısını yapardım ama kafamı "soket, .socket (socket.AF_INET ...) hattı etrafında alamıyorum - amacı nedir? – Kev1n91

    0

    Çoğu durumda, bir kez bağlantı kabul edilir yeni bir iş parçacığı veya süreci açılacaktır. Bağlantıyı kapatmak için while döngüsünü kırın. Çöp toplama işlemi iş parçacığı veya işlemi kaldıracak, ancak katılım hiçbirinin geride kalmamasını sağlayacaktır.

    Kalıcı soketler, kullanıcı kapandığında veya zaman aşımına uğradığında kapanır. Kalıcı olmayan, statik web sayfaları gibi bilgileri gönderdikten sonra kapanır.

    Python'da kalıcı bir soket sunucusuna iyi bir örnek. CPU'ya bağlı görevler için çoklu çekirdekler arasında çalışabileceği anlamına gelen çoklu işlemeyi kullanır. Daha yaygın olarak multithreading olarak bilinir.

    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

    çözüm

    1. sağ accept
    +4

    Bu tavsiyeyi takip ederek bugüne kadar yaptığım en kötü karardı. – Paradoxis

    +0

    Benimle çalışmak için 'settimeout()' ı buldum, bkz. Http://stackoverflow.com/a/41643863/143931. – fuenfundachtzig

    İlgili konular