import socketserver socketserver.BaseServer(server_address, RequestHandlerClass)
server_address
- семейство адресов к которому принадлежит сокет сервера,RequestHandlerClass
- пользовательский класс обработчика запросов.Класс BaseServer()
представляет собой суперкласс всех объектов Server
модуля socketserver
.
Этот класс определяет интерфейс, указанный ниже, но не реализует большинство методов, которые выполняются в подклассах.
Два аргумента класса хранятся в соответствующих атрибутах Server.server_address
и Server.RequestHandlerClass
.
Server
.Server.fileno()
файловый дескриптор сокета,Server.handle_request()
обрабатывает единичный запрос,Server.serve_forever()
запускает цикл сервера,Server.service_actions()
отвечает за очистку ресурсов,Server.shutdown()
останавливает цикл сервера,Server.server_close()
закрывает и очищает сервер,Server.address_family
семейство адресов сокета сервера,Server.RequestHandlerClass
класс обработчика запросов,Server.server_address
адрес, который слушает сервер,Server.socket
объект сокета, слушающий входящие запросы,Server.allow_reuse_address
повторное использование адреса,Server.request_queue_size
размер очереди запросов,Server.socket_type
тип сокета сервера,Server.timeout
таймаут запросов,Server.finish_request()
обрабатывает запрос,Server.get_request()
принимает запрос от сокета,Server.handle_error()
вызывается, если .handle()
вызывает исключение,Server.handle_timeout()
вызывается, когда таймаут истек, а запросы не получены,Server.process_request()
вызывает метод .finish_request()
,Server.server_activate()
вызывается для активации сервера,Server.server_bind()
привязывает сокет к адресу,Server.verify_request()
проверяет, может ли сервер обработать запрос,Server.fileno()
:Метод Server.fileno()
возвращает целочисленный файловый дескриптор для сокета, на котором прослушивается сервер. Этот метод чаще всего передается в модуль selectors
, чтобы разрешить мониторинг нескольких серверов в одном процессе.
Server.handle_request()
:Метод Server.handle_request()
обрабатывает единичный запрос. Этот метод вызывает следующие методы по порядку:
Если предоставленный пользователем метод .handle()
класса обработчика вызывает исключение, то будет вызван серверный метод Server.handle_error()
.
Если в течение Server.timeout
секунд не будет получен запрос, то будет вызван метод Server.handle_timeout()
, а метод Server.handle_request()
вернет результат.
Server.serve_forever(poll_interval=0.5)
:Метод Server.serve_forever()
говорит серверу - обрабатывать запросы клиентов до явного вызова метода Server.shutdown()
.
Метод осуществляет опрос на завершение работы каждые poll_interval
секунд. Игнорирует атрибут тайм-аута. Он также вызывает метод Server.service_actions()
, который может использоваться подклассом или миксином для предоставления действий, специфичных для данной службы.
Например, класс socketserver.ForkingMixIn
использует метод Server.service_actions()
для очистки дочерних зомби процессов.
Server.service_actions()
:Метод Server.service_actions()
вызывается в цикле Server.serve_forever()
.
Метод может быть переопределен подклассами или классами миксинов для выполнения действий, специфичных для данной службы, таких как действия по очистке задействованных ресурсов.
Server.shutdown()
:Метод Server.shutdown()
говорит серверу, что бы цикл Server.serve_forever()
остановился, при этом дождался завершения обработки запросов подключенных клиентов.
Метод Server.shutdown()
должен быть вызван, пока Server.serve_forever()
работает в другом потоке, иначе он будет заблокирован.
Server.server_close()
:Метод Server.server_close()
закрывает и очищает сервер. Метод может быть переопределен.
Server.address_family
:Атрибут Server.address_family
- это семейство адресов, к которому принадлежит сокет сервера.
Распространенными примерами являются socket.AF_INET
и socket.AF_UNIX
.
Server.RequestHandlerClass
:Атрибут Server.RequestHandlerClass
представляет собой пользовательский класс обработчика запросов.
Экземпляр этого класса создается для каждого запроса.
Server.server_address
:Атрибут Server.server_address
- это адрес, который слушает сервер.
Формат адресов зависит от семейства протоколов (подробности в документации по модулю socket
).
Для интернет-протоколов это кортеж, содержащий строку с адресом и целочисленный номер порта: ('127.0.0.1', 80)
.
Server.socket
:Атрибут Server.socket
представляет собой объект сокета, на котором сервер будет прослушивать входящие запросы.
Server.allow_reuse_address
:Переменная Server.allow_reuse_address
определяет, разрешит ли сервер повторное использование адреса. По умолчанию это False
и ее можно установить в подклассах для изменения политики.
Server.request_queue_size
:Переменная Server.request_queue_size
определяет размер очереди запросов.
Если обработка одного запроса занимает много времени, то любые запросы, поступающие, пока сервер занят, помещаются в очередь, вплоть до количества request_queue_size
. Как только очередь будет заполнена, дальнейшие запросы от клиентов получат ошибку "Connection denied".
Значение по умолчанию обычно 5, но это может быть отменено подклассами.
Server.socket_type
:Переменная Server.socket_type
определяет тип сокета, используемого сервером: socket.SOCK_STREAM
и socket.SOCK_DGRAM
- это два общих значения.
Server.timeout
:Переменная Server.timeout
определяет продолжительность тайм-аута, измеряемая в секундах, или None
, если тайм-аут не требуется.
Если метод Server.handle_request()
не получает входящих запросов в течение периода ожидания, то вызывается метод Server.handle_timeout()
.
Следующие методы могут быть переопределены подклассами базовых серверных классов, таких как socketserver.TCPServer
.
Эти методы, скорее всего, не будут полезны конечным пользователям.
Server.finish_request(request, client_address)
:Метод Server.finish_request()
фактически обрабатывает запрос, создавая экземпляр Server.RequestHandlerClass
и вызывая его метод .handle()
.
Server.get_request()
:Метод Server.get_request()
должен принимать запрос от сокета и возвращать кортеж из двух частей, содержащий новый объект сокета, который будет использоваться для связи с клиентом и адрес клиента.
Server.handle_error(request, client_address)
:Метод Server.handle_error()
вызывается, если метод .handle()
экземпляра Server.RequestHandlerClass
вызывает исключение.
Действие по умолчанию состоит в том, чтобы распечатать трассировку до стандартной ошибки и продолжить обработку дальнейших запросов.
Изменено в Python 3.6: Теперь вызываются только исключения, производные от класса Exception.
Server.handle_timeout()
:Метод Server.handle_timeout()
вызывается, когда для атрибута Server.timeout
установлено значение, отличное от None
и период тайм-аута истек, а запросы не получены.
Действие по умолчанию для серверов, обрабатывающих запросы клиентов в отдельных процессах, заключается в определении статуса всех дочерних процессов, которые завершились.
На серверах, обрабатывающих запросы клиентов в отдельных потоках этот метод ничего не делает.
Server.process_request(request, client_address)
:Метод Server.process_request()
вызывает метод Server.finish_request()
для создания экземпляра Server.RequestHandlerClass
.
При желании этот метод может создать новый процесс или поток для обработки запроса (классы ForkingMixIn
и ThreadingMixIn
).
Server.server_activate()
:Метод Server.server_activate()
вызывается конструктором сервера для активации сервера. Поведение по умолчанию для TCP-сервера просто вызывает метод `Socket.listen() в сокете сервера. Может быть переопределен.
Server.server_bind()
:Метод Server.server_bind()
вызывается конструктором сервера для привязки сокета к желаемому адресу. Может быть переопределен.
Server.verify_request(request, client_address)
:Метод Server.verify_request()
должен возвращать логическое значение. Если значение равно True
, то запрос будет обработан, а если False
, то запрос будет отклонен.
Этот метод переопределяют, чтобы реализовать контроль доступа для сервера. Реализация по умолчанию всегда возвращает True
.
Изменено в Python 3.6: добавлена поддержка протокола диспетчера контекста. Выход из диспетчера контекста эквивалентен вызову Server.server_close()
.
Серверная сторона:
# server.py import socketserver class MyUDPHandler(socketserver.BaseRequestHandler): """ Класс работает аналогично классу TCP, за исключением того, что `self.request` состоит из пары данных и клиентского сокета, а так как нет никакого соединения, то адрес клиента должен быть указан явно при отправке данных обратно через метод `sendto()`. """ def handle(self): data = self.request[0].strip() socket = self.request[1] print(f"{self.client_address[0]} прислал:") print(data) socket.sendto(data.upper(), self.client_address) if __name__ == "__main__": HOST, PORT = "localhost", 9999 with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server: server.serve_forever()
Клиентская сторона для проверки работы UDP сервера. Первым запускается серверная сторона. Клиент запускается в другом терминале. Сообщение клиенту формируется как параметр командной строки при запуске клиентского скрипта, например $ python3 client.py Hello world!
# client.py import socket, sys HOST, PORT = "localhost", 9999 data = " ".join(sys.argv[1:]) # `socket.SOCK_DGRAM` - это тип сокета, # используемый для сокетов UDP sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Как можно видеть, нет никакого вызова метода `connect()`. # UDP не имеет никаких соединений. Данные отправляются # непосредственно получателю через метод `.sendto()`. sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT)) received = str(sock.recv(1024), "utf-8") print(f"Послали: {data}") print(f"Получили: {received}")