Методы сокетов, используемые сервером

metody soketov ispolzuemye serverom Сетевые сценарии

Прежде чем увидеть эти программы в действии, коротко рассмотрим, как здесь клиент и сервер выполняют свои функции. Оба они представляют достаточно простые примеры сценариев, использующих сокеты, но иллюстрируют общую схему последовательности вызовов методов, применяемую в большинстве программ, использующих сокеты. В действительности это достаточно стереотипный программный код: большинство программ сокетов обычно выполняет вызовы тех же методов сокетов, что и наши два сценария, поэтому разберем каждую строку в существенных местах этих сценариев.

Программы, подобные приведенной в примере 12.1, предоставляющие услуги другим программам с помощью сокетов, обычно начинают работу с такой последовательности вызовов:

sockobj = socket(AF_INET, SOCK_STREAM)

Здесь с помощью модуля socket создается объект сокета TCP. Имена AF_INET и SOCK_STREAM принадлежат предопределенным переменным, импортируемым из модуля socket; их совместное применение означает «создать сокет TCP/IP», стандартное средство связи для Интернета. Более точно, AF_INET означает протокол адресов IP, а SOCK_STREAM означает протокол передачи TCP. Комбинация AF_INET/SOCK_STREAM используется по умолчанию, потому что является наиболее типичной, но при этом обычно она указывается явно.

При использовании в этом вызове других имен можно создавать такие объекты, как сокеты UDP без логического соединения (второй параметр SOCK_DGRAM) и доменные сокеты Unix на локальном компьютере (первый параметр AF_UNIX), но в данной книге мы этого делать не будем. Смотрите подробности относительно этих и других параметров модуля socket в руководстве по библиотеке Python. Использование сокетов других типов предполагает использование иных стереотипных форм программного кода.

sockobj.bind((myHost, myPort))

Связывает объект сокета с адресом — для IP-адресов передается имя компьютера сервера и номер порта на этом компьютере. Здесь сервер идентифицирует компьютер и порт, связанные с сокетом. В серверных программах имя компьютера обычно задается пустой строкой (»), что означает компьютер, на котором выполняется сценарий (формально, все локальные и удаленные интерфейсы доступные на компьютере), а порт указывается как число за пределами диапазона 0-1023 (зарезервированного для стандартных протоколов, описывавшихся выше).

Обратите внимание, что у каждой поддерживаемой службы сокетов должен быть свой номер порта. Если попытаться открыть сокет на порту, который уже используется, Python возбудит исключение. Обратите также внимание на вложенные скобки в этом вызове — здесь для сокета с протоколом адресов AF_INET мы передаем методу bind адрес сокета хост/порт, как объект кортежа из двух элементов (для AF_UNIX передается строка). Технически метод bind принимает кортеж значений, соответствующий типу создаваемого сокета.

sockobj.listen(5)

Начинает ожидание входящих запросов на соединение от клиентов и позволяет помещать в очередь ожидания до пяти запросов. Передаваемое значение устанавливает количество входящих клиентских запросов, помещаемых операционной системой в очередь перед тем, как начать отклонять новые запросы (что происходит только тогда, когда сервер не успевает обрабатывать запросы и очередь переполняется). Для большинства программ, работающих с сокетами, обычно достаточно значения 5. Этому методу следует передавать число не менее 1.

После этого сервер готов к принятию запросов соединения от клиентских программ, выполняющихся на удаленных компьютерах (или том же самом компьютере), и входит в бесконечный цикл ожидания их поступления:

connection, address = sockobj.accept()

Ждет поступления от клиента нового запроса на соединение. Когда он поступит, метод accept вернет новый объект сокета, через который можно передавать данные соединившемуся клиенту и получать их от него. Соединение осуществляет объект sockobj, но связь с клиентом происходит через новый сокет, connection. Этот метод возвращает кортеж из двух элементов, где address является интернет-адресом соединившегося клиента. Метод accept может вызываться многократно, чтобы обслужить несколько клиентов. Поэтому каждый вызов возвращает новый сокет, через который происходит связь с конкретным клиентом.

Установив соединение с клиентом, мы попадаем в другой цикл, в котором получаем от клиента данные блоками по 1024 байта и отправляем каждый блок обратно клиенту:

data = connection.recv(1024)

Читает до 1024 байтов из очередного сообщения, посланного клиентом (то есть поступившего из сети или через соединение IPC), и возвращает их сценарию в виде строки. При завершении работы клиентом возвращается пустая строка байтов — когда клиент закрывает свой конец сокета, возвращается признак конца файла. connection.send(‘Echo=>’ + data)

Отправляет последний полученный блок данных обратно программе клиента, предварив его строкой ‘Echo=>’. Программа клиента получает эти отправленные ей данные с помощью метода recv. Технически, этот метод старается отправить максимально возможное количество данных и возвращает количество фактически отправленных байтов. Для обеспечения надежной передачи данных некоторые программы могут повторять передачу неотправленных фрагментов или использовать метод connection.sendall для принудительной передачи всех байтов.

connection.close()

Закрывает соединение с данным конкретным клиентом.

Использованная литература:

Марк Лутц — Программирование на Python, 4-е издание, II том, 2011

Каталог сайтов Всего.ру
Оцените статью
Секреты программирования
Добавить комментарий