Python TCP-сервер выдает OSError: [WinError 10057] при вызове socket.shutdown (1) - PullRequest
0 голосов
/ 12 марта 2020

У меня довольно сложный сервер TCP / IP, который подключается к нескольким клиентам. Я столкнулся с проблемой, когда мои клиенты не обновлялись из-за закрытия сокета. Я считаю, что мне нужно вызывать socket.shutdown () и socket.close (), чтобы иметь возможность отправлять рекомендации по закрытию сервера всем клиентам. Тем не менее, я получаю ошибку ОС всякий раз, когда я вызываю socket.shutdown ().

OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied

Кто-нибудь знает, почему это происходит? Или каким-то другим способом закрыть сокет, отправляя рекомендации всем подключенным клиентам? Я всегда мог написать пользовательскую команду, которая сбрасывает все клиенты перед вызовом socket.close (), но что-то не так с моим сервером. Ниже приведен минимальный воспроизводимый пример.

import socket
import selectors

class server_test:

    host = ''
    port = 12345

    sel = selectors.DefaultSelector()

    def __init__(self):
        self.start_server()
        self.stop_server()

    #Server Functions    
    def start_server(self):        
        self.lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.lsock.bind((self.host, self.port))
        self.lsock.listen()
        print("Server starting, listening on ",. (self.host, self.port))
        self.lsock.setblocking(False)
        self.sel.register(self.lsock, selectors.EVENT_READ, data=None)


    def stop_server(self):
        print("Shutting server down")
        self.lsock.shutdown(1)
        self.lsock.close()

1 Ответ

1 голос
/ 13 марта 2020

Я считаю, что мне нужно вызвать и socket.shutdown (), и socket.close (), чтобы иметь возможность отправить уведомление о закрытии сервера всем клиентам.

Нет. shutdown(1) на подключенном сокете отправит FIN равноправному узлу, чтобы указать, что локальная система не будет отправлять больше данных, но на самом деле может принять больше данных. A shutdown(0) прекратит получать данные локально и отклонит любые данные, отправленные узлом. A close() по существу объединяет shutdown(1) и shutdown(0).

    self.lsock.listen()
    ...
    self.lsock.shutdown(1)

Вы пытаетесь сообщить партнеру self.lsock, что больше не будете отправлять данные. Но self.lsock - это локальный сокет слушателя, который сам не подключен и, следовательно, не имеет однорангового узла. Поскольку вы, таким образом, пытаетесь выполнить операцию, требующую подключения сокета к разъему, который не подключен (только прослушивание), это приведет к ошибке "... сокет не подключен ..." .

Если вы хотите завершить соединение со всеми клиентами, вам действительно нужно позвонить shutdown или close на все подключенные сокеты (то есть результат self.lsock.accept(), а не на сокете слушателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...