2013-05-24 17 views
6

Mam problem podczas próby poznania gniazd dla komunikacji sieciowej. Zrobiłem prosty wątek, który nasłuchuje połączeń i tworzy procesy do łączenia klientów. Mój problem polega jednak na tym, że nie mogę uzyskać prawidłowego przyłączenia się wątku, ponieważ nie znalazłem sposobu na anulowanie połączenia socket.accept() - wywołanie kiedy chcę opuścić program.Gniazdo nasłuchiwania w wątku python

Mój kod wygląda następująco;

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

udało mi się dostać do zamknięcia programu przez ustawienie self.setDaemon(True) i po prostu wyjście z programu głównego, podając wszystko do wielkiej śmieciarza - ale to wydaje się być złym rozwiązaniem. Próbowałem również ustawić limit czasu dla gniazda, ale to powoduje uzyskanie [Errno 35] Resource temporarily unavailable (niezależnie od faktycznego limitu czasu, nawet gdy ustawiłem go na lata ...).

Co robię źle? Czy zaprojektowałem wątek głupio, czy też przeoczyłem coś o akceptowaniu połączeń?

+0

'ale to wydaje się złym rozwiązaniem' - to działa? Jeśli nie lubisz, gdy system operacyjny zakończy wszystkie wątki, możesz spróbować zamknąć gniazdo nasłuchiwania z głównego lub innego wątku. Zwykle powoduje to, że accept() zwraca "wcześnie" z błędem. Działa na większości systemów operacyjnych/języków, ale nie jest wypróbowany w Pythonie, więc nie jest odpowiedzią. –

+0

To działa - ale mam wrażenie, że nie bardzo dobrze traktuję potencjalnych klientów. Opublikowalem rozwiązanie, które wydaje się milsze, ponieważ pozwala na ukończenie kodu, ale wciąż wydaje się nieco dziwne, ponieważ kończy się tworzeniem nowego procesu, który będę musiał od razu dołączyć. – Norling

Odpowiedz

8

Jednym ze sposobów na zamknięcie wątku wydaje się być nawiązanie połączenia z gniazdem, a tym samym kontynuowanie wątku do zakończenia.

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

To działa, ale nadal czuje się jak może nie być optymalna ...

+0

Tak - "sztucznie" spełniające warunki oczekiwania, (jak tutaj otwarcie tymczasowego połączenia lokalnego), znajduje się również w worku "zatrzymanych zablokowanych wątków". –

+0

Wydaje się, że znasz te rzeczy! ^^ Dzięki za pomoc! Jakieś inne sztuczki, które mógłbym spróbować? – Norling

+0

Obecnie próbuję zrozumieć ten problem/kod - zrobiłbym to samo, ale nie mogę się skupić na linii "socket, .socket (socket.AF_INET ...) - jaki jest jej cel? – Kev1n91

0

W większości przypadków będzie otworzyć nowy wątek lub proces gdy połączenie jest akceptowana. Aby zamknąć połączenie, przerwij pętlę while. Wyrzucanie śmieci usunie wątek lub proces, ale dołączenie zapewni, że żaden nie zostanie pozostawiony.

Trwałe gniazda zamykają się, gdy użytkownik je zamknie lub upłynął limit czasu. Nietrwałe, podobnie jak statyczne strony internetowe, zostaną zamknięte po wysłaniu informacji.

Oto dobry przykład trwałego serwera gniazd w języku Python. Wykorzystuje proces wieloprocesowy, co oznacza, że ​​może działać w wielu rdzeniach dla zadań związanych z procesorem. Bardziej znany jako wielowątkowość.

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

Częściowo przetestowane rozwiązanie

  1. Put self.socket.settimeout(0.1) tuż przed while
  2. Put conn.settimeout(None) zaraz po accept
+4

Poniższa porada była zdecydowanie najgorszą decyzją, którą podjąłem przez cały dzień – Paradoxis

+0

Znalazłem 'settimeout()' do pracy dla mnie, zobacz http://stackoverflow.com/a/41643863/143931. – fuenfundachtzig

Powiązane problemy