Сокеты Python - сохранить сокет в живых? - PullRequest
5 голосов
/ 25 февраля 2011

У меня небольшие проблемы с сокетами в Python. Всякий раз, когда кто-то подключается, он работает нормально, но если он отключается, программа сервера закрывается. Я хочу, чтобы программа сервера оставалась открытой после закрытия клиента. Я использую цикл True для поддержания соединения в действии, но как только клиент закрывает соединение, сервер закрывает соединение.

Вот клиент:

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:  ')

Вот сервер:

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)

Ответы [ 2 ]

5 голосов
/ 25 февраля 2011

Если клиент закрывает соединение, вы хотите, чтобы он закрыл сокет.

Похоже, что здесь есть некоторая несогласованность, которую я постараюсь уточнить. Когда вы создаете сокет, привязываетесь и слушаете, вы открыли дверь, чтобы другие могли приходить и связываться с вами.

Как только клиент подключается к вам, и вы используете вызов accept(), чтобы принять соединение и получить новый сокет (conn), который возвращается вам для взаимодействия с клиентом. Ваш оригинальный сокет прослушивания все еще там и активен, и вы все еще можете использовать его для приема новых подключений.

Глядя на свой код, вы, вероятно, хотите сделать что-то вроде этого:

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)

Обратите внимание, что это только отправная точка, и, как другие предположили, вы, вероятно, захотите использовать select() наряду с разветвлением процессов или порождением потоков для обслуживания каждого клиента.

2 голосов
/ 25 февраля 2011

Ваш код принимает только одно соединение - цикл обрабатывает только первое принятое соединение и завершается, как только оно потеряно. Вот так существует ваш сервер:

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

Вам нужно будет принять несколько соединений, одновременно обрабатывая каждое из них в своем собственном цикле. Обратите внимание, что это не обязательно должен быть реальный цикл для каждого сокета, вы можете использовать подход на основе select, чтобы запросить, с каким из сокетов связано событие (данные доступны, потеря соединения и т. Д.), А затем только обработать эти розетки, все в одной петле.

Вы также можете использовать многопоточный / многопроцессный подход, когда каждый клиент работает в отдельном потоке или процессе - я полагаю, что при воспроизведении вы не столкнетесь с проблемами масштабирования.

См:

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

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

...