2011-02-24 13 views
5

Mam trochę problemów z gniazdami w Pythonie. Za każdym razem, gdy ktoś się połączy, działa dobrze, ale jeśli się rozłączą, program serwera zostanie zamknięty. Chcę, aby program serwera pozostawał otwarty po zamknięciu klienta. Używam pętli True, aby utrzymać połączenie przy życiu, ale gdy klient zamknie połączenie, serwer zamknie jego połączenie.Gniazda Pythona - utrzymują gniazdo przy życiu?

Oto klient:

import socket, sys 
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
host = sys.argv[1] 
port = int(sys.argv[2]) 
conn.connect((host, port)) 

print("Connected to host " + sys.argv[1]) 
td = 1 
while td == 1: 
    msg = raw_input('MSG: ') 

Oto server:

import socket, sys 

socket.setdefaulttimeout(150) 
host = ''    
port = 50005 
socksize = 1024 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host, port)) 
print("Server started on port: %s" % port) 
s.listen(1) 
print("Now listening...\n") 
conn, addr = s.accept() 

while True: 
    print 'New connection from %s:%d' % (addr[0], addr[1]) 
    data = conn.recv(socksize) 
    if not data: 
     break 
    elif data == 'killsrv': 
     conn.close() 
     sys.exit() 
    else: 
     print(data) 
+1

Czy używasz n + 1 gniazd dla n połączeń? Potrzebujesz jednego gniazda, które nasłuchuje przez cały czas. To gniazdo nasłuchu akceptuje nowe połączenia i otwiera kolejne gniazdo za każdym razem, gdy żądane jest połączenie. – Penang

+0

Czy możesz wysłać krótki fragment kodu, aby zademonstrować problem? – SimonJ

+0

n + 1 gniazdka? Nie jestem pewien, czy podążam. Czy możesz wyjaśnić nieco więcej? – AustinM

Odpowiedz

4

Jeśli klient zamyka połączenie, chcesz go zamknąć gniazdo.

Wygląda na to, że jest tu trochę rozłączenia, które spróbuję rozwinąć. Kiedy tworzysz gniazdo, bindujesz i słuchasz, stworzyłeś otwarte drzwi dla innych, by przychodzić i nawiązywać połączenia z tobą.

Po nawiązaniu połączenia z klientem, należy użyć wywołania accept(), aby zaakceptować połączenie i uzyskać nowe gniazdo (conn), które jest zwracane w celu interakcji z klientem. Twoje oryginalne gniazdo nasłuchujące jest nadal aktywne i możesz nadal używać go do akceptowania nowych połączeń.

Patrząc na kodzie, prawdopodobnie chcesz zrobić coś takiego:

while True: 
    print("Now listening...\n") 
    conn, addr = s.accept() 

    print 'New connection from %s:%d' % (addr[0], addr[1]) 
    data = conn.recv(socksize) 
    if not data: 
     break 
    elif data == 'killsrv': 
     conn.close() 
     sys.exit() 
    else: 
     print(data) 

Zwróć uwagę, że jest to tylko punkt wyjścia, jak i inni sugerują prawdopodobnie chcesz użyć select() wraz z rozwidlone off przetwarza lub spawnie wątki do obsługi każdego klienta.

+0

Dzięki temu wydaje się działać, ale mam inny problem. Jeśli nadal wysyłam wiadomości, klient ostatecznie zamarza. Nie mam pojęcia dlaczego. – AustinM

+0

Czy możesz rozwinąć swój kod klienta i jak wysyła dane? – Jeff

2

kod jest przyjmowanie tylko jednego połączenia - pętla ta dotyczy tylko pierwszego przyjętą połączenie i kończy się tak szybko jak przegrał. W ten sposób Twój serwer istnieje:

data = conn.recv(socksize) 
if not data: 
    break 

Co musisz zrobić, to zaakceptować kilka połączeń, podczas pracy z każdym z nich w jego własnej pętli. Zauważ, że nie musi to być prawdziwa pętla dla każdego gniazda, możesz użyć metody opartej na select, aby sprawdzić, które z gniazd ma powiązane z nim zdarzenie (dostępne dane, utracone połączenia itp.), A następnie przetwarzać tylko te gniazda , wszystko w tej samej pętli.

Można również użyć podejścia wielowątkowego/wieloprocesowego, zajmującego się każdym klientem w jego własnym wątku lub procesie - domyślam się, że podczas zabawy nie natkniesz się na problemy z skalowaniem.

Patrz:

http://docs.python.org/library/select.html

http://docs.python.org/library/multiprocessing.html

+1

Dzięki. Czy mógłbyś podać mi jakiś przykład, jak używać select z gniazdami? – AustinM

+0

@AustinM Po drugie ten –

Powiązane problemy