2010-09-07 23 views
5
import socket 
backlog = 1 #Number of queues 

sk_1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sk_2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

local = {"port":1433} 
internet = {"port":9999} 

sk_1.bind (('', internet["port"])) 
sk_1.listen(backlog) 

sk_2.bind (('', local["port"])) 
sk_2.listen(backlog) 

Zasadniczo mam ten kod. Próbuję słuchać na dwóch portach: 1433 i 9999. Ale to nie działa.Python: Słuchaj na dwóch portach

Jak mogę odsłuchać na dwóch portach, w tym samym skrypcie python ??

Odpowiedz

4

Kod tej pory jest w porządku, jak dalece jak to jest (oprócz tego, że zaległości z 1 wydaje się nadmiernie surowe), problem oczywiście pochodzi podczas próby accept połączenia na obu gniazda słuchania, ponieważ accept jest normalnie blokowanie połączenia (i "odpytywanie" przez próbę akceptacji z krótkimi przerwami na obu gniazdach na przemian spowoduje spalenie cykli maszynowych bez żadnego dobrego celu).

select na ratunek! -) select.select (lub na lepszą OSs select.poll lub nawet select.epoll lub select.kqueue ... ale stare dobre select.select prace wszędzie! -) pozwoli Ci wiedzieć, które gniazdo jest gotowy i kiedy, więc może odpowiednio accept. W ramach tych linii, asyncore i asynchat zapewniają nieco więcej organizacji (i niezależny framework twisted, oczywiście, dodaje lot takiej "asynchronicznej" funkcjonalności).

Alternatywnie, można poświęcić osobne wątki do obsługi dwóch gniazd słuchanie, ale w tym przypadku, jeśli funkcjonalność różnych gniazd musi wpływać na te same współdzielonych struktur danych, koordynacja (blokowanie & c) może stać się drażliwy. Z pewnością polecam wypróbowanie metody asynchronicznej pierwszy - to rzeczywiście prostsze, jak również oferuje możliwości znacznie lepsze osiągi! -)

+0

Ale część, która nie działa, to dwa wiązania. – mRt

+0

@ mRt, jakie objawy obserwujecie przy wywołaniach "bind"? Wydają się poprawne, ponieważ wiążą dwa porty na wszystkich dostępnych interfejsach (to oczywiście oznacza "host" w pustym łańcuchu). –

10

fantazyjne spodnie sposób to zrobić, jeśli chcesz używać Pythona STD-lib byłoby używać SocketServer z ThreadingMixin - choć sugestia "wybierz" jest prawdopodobnie bardziej wydajna.

Mimo że definiujemy tylko jeden ThreadedTCPRequestHandler, można go łatwo przekształcić w taki sposób, że każdy detektor ma swój własny unikalny program obsługi i powinno być dość banalne, aby zawinąć tworzenie serwera/wątku w jedną metodę, jeśli jest to coś, co lubisz. .

#!/usr/bin/python 

import threading 
import time 
import SocketServer 

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): 

    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print "%s wrote: " % self.client_address[0] 
     print self.data 
     self.request.send(self.data.upper()) 

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 
    pass 

if __name__ == "__main__": 

    HOST = '' 
    PORT_A = 9999 
    PORT_B = 9876 

    server_A = ThreadedTCPServer((HOST, PORT_A), ThreadedTCPRequestHandler) 
    server_B = ThreadedTCPServer((HOST, PORT_B), ThreadedTCPRequestHandler) 

    server_A_thread = threading.Thread(target=server_A.serve_forever) 
    server_B_thread = threading.Thread(target=server_B.serve_forever) 

    server_A_thread.setDaemon(True) 
    server_B_thread.setDaemon(True) 

    server_A_thread.start() 
    server_B_thread.start() 

    while 1: 
     time.sleep(1)