Несколько вопросов относительно коммуникации клиента с сервером (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!")

Как я понял, на стороне сервера, я принимаю объект сокета клиента, и значит могу закрыть этот сокет соответственно. Мои вопросы:

  1. Где нужно закрывать сокет клиента - на стороне сервера, или на стороне клиента? Есть ли разница?
  2. Если я закрою его в серверном модуле, что произойдет с объектом сокета в клиентском модуле? Он становится None Type? Или остается прежним?
  3. Что происходит после socket.close()? Как я понимаю, даже после того, как я выполнил этот метод на стороне клиента, из-за while True моя программа все еще может дойти до функции socket.recv() и столкнуться с ошибками. Но когда я выполняю socket.close() на стороне сервера - я не получаю такой ошибки на стороне клиента. Есть ли способ правильно закрыть сокет на стороне клиента? (за исключением try/except)
  4. Если я хочу отключиться, мне нужно отправить сообщение на сервер и закрыть клиентский сокет на стороне сервера? Нужно ли мне потом делать это на стороне клиента?

Ответы (1 шт):

Автор решения: Кимерченко

Открыл соединение - сам его и заверши. Клиент закрывает свой сокет, сервер - приёмный conn. Сервер закрыл соединение = клиенту в recv() прилетит b''. Попробуешь читать дальше - получишь "Bad file descriptor". close() удаляет дескриптор из ядра; после этого сокет неактивен, хоть табличку вешай. Ошибки обрабатываются через try/except - это нормально, другого способа нет. Чистый выход: клиент шлёт "пока", делает shutdown(SHUT_WR); сервер дочитывает, закрывает conn; клиент завершает своим close().

→ Ссылка