Сообщить об ошибке.

Класс BaseServer() модуля socketserver в Python

Атрибуты и методы объекта сервера Server

Синтаксис:

import socketserver

socketserver.BaseServer(server_address, RequestHandlerClass)

Параметры:

  • server_address - семейство адресов к которому принадлежит сокет сервера,
  • RequestHandlerClass - пользовательский класс обработчика запросов.

Описание:

Класс BaseServer() представляет собой суперкласс всех объектов Server модуля socketserver.

Этот класс определяет интерфейс, указанный ниже, но не реализует большинство методов, которые выполняются в подклассах.

Два аргумента класса хранятся в соответствующих атрибутах Server.server_address и Server.RequestHandlerClass.

Атрибуты и методы объекта Server.

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}")