Вы создаете сокет в клиенте с tcp.make_client
.Затем вы используете этот сокет для подключения к серверу через tcp.client_connect
.Предположительно, вы успешно получили новый номер порта обратно с сервера.Но затем вы пытаетесь повторно использовать тот же сокет для подключения к этим портам.
Это примерная причина вашей ошибки: сокет может использоваться только для одного соединения TCP,Если вы хотите создать новое соединение, вы должны сначала создать новый сокет.
При этом, если вы просто пытаетесь создать сервер, который будет принимать несколько соединений, вы делаете это слишком сложным.Сервер может получать любое количество подключений через свой единственный порт прослушивания, если каждый клиент использует различную комбинацию адреса / порта.
Один из способов структурировать это на сервере - это что-то вроде этого:
# Create and bind listening socket
lsock = socket.socket()
lsock.bind(('', port))
lsock.listen(1)
while True:
csock, addr = lsock.accept()
print("Got connection from {}".format(addr))
# Start sub-process passing it the newly accepted socket as argument
subs = Process(target=start, args=(csock, ))
subs.start()
# Close our handle to the new socket (it will remain open in the
# sub-process which will use it to talk to the client)
csock.close()
# NOTE: do not call subs.join here unless you want the parent to *block*
# waiting for the sub-process to finish (and if so, what is the point in
# creating a sub-process?)
Есть также несколько других способов сделать это: вы можете создать несколько потоков для обработки нескольких соединений, или вы можете обрабатывать все соединения в одном потоке, используя select
или с помощью асинхронного ввода-вывода.
Клиент, как правило, намного проще - так как он обычно заботится только о своем собственном соединении - и не заботится о том, каким образом реализован сервер:
sock = socket.socket()
sock.connect((ip, port))
while True:
sock.send(...)
sock.recv(...)
Если клиент не хочет снова подключиться к тому же серверу, он просто создает второй сокет и вызывает метод connect
с тем же IP-адресом и портом сервера.
Обычно клиенту никогда не требуетсяуказать свой собственный порт, только порт сервера.Он просто вызывает connect
, и клиентская операционная система выбирает для него неиспользуемый порт.Поэтому в первый раз, когда клиент создает сокет и подключает его ( к порту прослушивания сервера ), клиентская ОС может выбрать порт 50001. В следующий раз, когда он создает и подключает сокет, он может получить50002 и тд.(Точные номера портов зависят от реализации операционной системы и других факторов, например, от того, какие другие программы работают и создают соединения.)
Итак, с учетом IP-адреса клиента 192.168.0.101 и IP-адреса сервера 192.168.0.102, ипри условии, что сервер прослушивает порт 8000, это приведет к следующим двум соединениям:
- (192.168.0.101/50001) ====> (192.168.0.102/8000)
- (192.168.0.101/50002) ====> (192.168.0.102/8000)