Несколько вопросов относительно коммуникации клиента с сервером (python socket module)
У меня есть 2 скрипта: первый - tcp сервер который в while True принимает новых клиентов и контролирует в отдельных потоках каждого из них. На стороне клиента у меня обычный функционал - приём и отправка простых сообщений на сервер. То, что мне непонятно - как правильно закрыть socket клиента.
Вот код который я для этого использую:
def __on_s_close(self):
try:
self.__socket.shutdown(socket.SHUT_RDWR)
except socket.error as e:
logger.error(f"error while shutting down: {e}")
finally:
self.__socket.close()
self.__socket = None
logger.debug("client terminated from client module!")
Как я понял, на стороне сервера, я принимаю объект сокета клиента, и значит могу закрыть этот сокет соответственно. Мои вопросы:
- Где нужно закрывать сокет клиента - на стороне сервера, или на стороне клиента? Есть ли разница?
- Если я закрою его в серверном модуле, что произойдет с объектом сокета в клиентском модуле? Он становится
None Type? Или остается прежним? - Что происходит после
socket.close()? Как я понимаю, даже после того, как я выполнил этот метод на стороне клиента, из-заwhile Trueмоя программа все еще может дойти до функцииsocket.recv()и столкнуться с ошибками. Но когда я выполняюsocket.close()на стороне сервера - я не получаю такой ошибки на стороне клиента. Есть ли способ правильно закрыть сокет на стороне клиента? (за исключениемtry/except) - Если я хочу отключиться, мне нужно отправить сообщение на сервер и закрыть клиентский сокет на стороне сервера? Нужно ли мне потом делать это на стороне клиента?
Ответы (1 шт):
Открыл соединение - сам его и заверши. Клиент закрывает свой сокет, сервер - приёмный conn.
Сервер закрыл соединение = клиенту в recv() прилетит b''. Попробуешь читать дальше - получишь "Bad file descriptor".
close() удаляет дескриптор из ядра; после этого сокет неактивен, хоть табличку вешай.
Ошибки обрабатываются через try/except - это нормально, другого способа нет.
Чистый выход: клиент шлёт "пока", делает shutdown(SHUT_WR); сервер дочитывает, закрывает conn; клиент завершает своим close().