справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
586 Глава 21. Работа с сетью и сокеты Модуль socket М одуль socket предоставляет доступ к стандартному интерфейсу сокетов BSD. Хотя этот интерфейс разрабатывался для системы UNIX, тем не ме- . Хотя этот интерфейс разрабатывался для системы UNIX, тем не ме- UNIX, тем не ме- , тем не ме- нее модуль socket может использоваться во всех платформах. Интерфейс сокетов разрабатывался для поддержки широкого разнообразия сетевых протоколов (IP, TIPC, Bluetooth и других). Однако наиболее часто исполь- IP, TIPC, Bluetooth и других). Однако наиболее часто исполь- , TIPC, Bluetooth и других). Однако наиболее часто исполь- TIPC, Bluetooth и других). Однако наиболее часто исполь- , Bluetooth и других). Однако наиболее часто исполь- Bluetooth и других). Однако наиболее часто исполь- и других). Однако наиболее часто исполь- зуемым является протокол Интернета (Internet Protocol, IP), который включает в себя оба протокола, TCP и UDP. В языке Python поддержива- TCP и UDP. В языке Python поддержива- и UDP. В языке Python поддержива- UDP. В языке Python поддержива- . В языке Python поддержива- Python поддержива- поддержива- ются обе версии протокола, IPv4 и IPv6, хотя версия IPv4 распространена намного шире. Следует заметить, что этот модуль находится на достаточно низком уровне, обеспечивая непосредственный доступ к сетевым функциям, предоставля- емым операционной системой. При разработке сетевых приложений может оказаться проще использовать модули, описываемые в главе 22, или мо- дуль SocketServer, описываемый в конце этой главы. Семейства адресов Некоторые функции из модуля socket требуют указывать семейство адре- сов. Семейство определяет, какой сетевой протокол будет использоваться. Ниже приводится список констант, которые определены для этой цели: Константа Описание AF_BLUETOOTH Протокол Bluetooth AF_INET Протокол IPv4 (TCP, UDP) AF_INET6 Протокол IPv6 (TCP, UDP) AF_NETLINK Протокол Netlink взаимодействия процессов AF_PACKET Пакеты канального уровня AF_TIPC Прозрачный протокол взаимодействия процессов (Transparent Inter-Process Communication protocol, TIPC) AF_UNIX Протоколы домена UNIX Из них наиболее часто употребляются семейства AF_INET и AF_INET6, пото- му что они представляют стандартные сетевые соединения. Семейство AF_BLUETOOTH доступно только в системах, поддерживающих его (обычно это встраиваемые системы). Семейства AF_NETLINK, AF_PACKET и AF_TIPC под- держиваются только в операционной системе Linux. Семейство AF_NETLINK используется для обеспечения скоростных взаимодействий между пользо- вательскими процессами и ядром Linux. Семейство AF_PACKET используется для прямого взаимодействия с уровнем передачи данных (например, для непосредственной работы с пакетами ethernet). Семейство AF_TIPC определя- ет протокол, используемый для обеспечения скоростных взаимодействий процессов в кластерах, действующих под управлением операционной си- стемы Linux (http://tipc.sourceforge.net/). Модуль socket 587 Типы сокетов Не которые функции в модуле socket дополнительно требуют указывать тип сокета. Тип сокета определяет тип взаимодействий (потоки или паке- ты) для использования с указанным семейством протоколов. Ниже приво- дится список констант, используемых для этой цели: Константа Описание SOCK_STREAM Поток байтов с поддержкой логического соединения, обеспе- чивающего надежность передачи данных (TCP) SOCK_DGRAM Дейтаграммы (UDP) SOCK_RAW Простой сокет SOCK_RDM Дейтаграммы с надежной доставкой SOCK_SEQPACKET Обеспечивает последовательную передачу записей с поддерж- кой логических соединений Наиболее часто в практике используются типы сокетов SOCK_STREAM и SOCK_ DGRAM , потому что они соответствуют протоколам TCP и UDP в семействе протоколов Интернета (IP). Тип SOCK_RDM является разновидностью прото- кола UDP, обеспечивающей доставку дейтаграмм, но не гарантирующей порядок их доставки (дейтаграммы могут поступать получателю не в том порядке, в каком они отправлялись). Тип SOCK_SEQPACKET используется для отправки пакетов через соединения, ориентированные на передачу пото- ка данных с сохранением порядка следования пакетов и их границ. Типы SOCK_RDM и SOCK_SEQPACKET не получили широкой поддержки, поэтому для обеспечения переносимости программ их лучше не использовать. Тип SOCK_RAW используется для низкоуровневого доступа к протоколу и может применяться для реализации специализированных операций, таких как отправка управляющих сообщений (например, сообщений ICMP). Обычно тип SOCK_RAW используется только в программах, которые предполагается выполнять с привилегиями суперпользователя или администратора. Не все типы сокетов поддерживаются всеми семействами протоколов. На- пример, используя семейство AF_PACKET для перехвата пакетов ethernet в си- ethernet в си- в си- стеме Linux, нельзя установить соединение для приема потока байтов, ука- Linux, нельзя установить соединение для приема потока байтов, ука- , нельзя установить соединение для приема потока байтов, ука- зав тип SOCK_STREAM. Вместо этого придется использовать тип SOCK_DGRAM или SOCK_RAW . Семейство AF_NETLINK поддерживает только тип SOCK_RAW. Адресация Чтобы обеспечить возможность взаимодействий через сокеты, необходимо указать адрес назначения. Форма адреса зависит от используемого семей- ства протоколов. AF_INET (IPv4) Для интернет-приложений, использующих протокол IPv4, адреса опреде- IPv4, адреса опреде- 4, адреса опреде- ляются в виде кортежа (host, port). Ниже приводятся два примера опреде- ления адресов: 588 Глава 21. Работа с сетью и сокеты (‘www.python.org’, 80) (‘66.113.130.182’, 25) Е сли в поле host передается пустая строка, это равносильно использованию константы INADDR_ANY, которая соответствует любому адресу. Обычно такой способ адресации используется на стороне сервера, когда создается сокет, принимающий соединения от любых клиентов. Если в поле host передает- ся значение ‘ DR_BROADCAST в API сокетов. Следует помнить, что при использовании имен хостов, таких как ‘www.py- www.py- .py- py- thon.org’ , для их преобразования в IP-адреса будет использоваться служба доменных имен (DNS). В зависимости от настроек службы DNS программа может получать каждый раз различные IP-адреса. Чтобы избежать этого, в случае необходимости можно использовать обычные адреса, такие как ‘66.113.130.182’ AF_INET6 (IPv6) Для протокола IPv6 адреса указываются в виде кортежа из 4 элементов ( host, port, flowinfo, scopeid) . В адресах IPv6 поля host и port имеют тот же смысл, что и в адресах IPv4, за исключением того, что в числовой форме адрес IPv6 обычно задается строкой, состоящей из восьми шестнадцате- IPv6 обычно задается строкой, состоящей из восьми шестнадцате- 6 обычно задается строкой, состоящей из восьми шестнадцате- ричных чисел, разделенных двоеточием, например: ‘FEDC:BA98:7654:3210:FE DC:BA98:7654:3210’ или ‘080A::4:1’ (в последнем случае два двоеточия, следу- ющие подряд, соответствуют недостающим группам чисел, состоящих из одних нулей). В поле flowinfo указывается 32-битное число, содержащее 24-битный иден- тификатор потока (младшие 24 бита) и 4-битное значение приоритета (сле- дующие 4 бита), старшие 4 бита зарезервированы. Идентификатор потока обычно используется, только когда отправителю необходимо разрешить специальные виды обработки трафика маршрутизаторами. В противном случае в поле flowinfo передается значение 0. В поле scopeid указывается 32-битное число, которое требуется только при работе с адресами локальной сети и локального сайта. Адреса локальной сети всегда начинаются с префикса ‘FE80:...’ и используются для взаимо- действий между компьютерами, находящимися в одной локальной сети (маршрутизаторы не передают локальные пакеты за пределы сети). В этом случае поле scopeid определяет индекс интерфейса, идентифицирующий конкретный сетевой интерфейс хоста. Эту информацию можно увидеть, воспользовавшись командой ‘ifconfig’ в UNIX или ‘ipv6 if’ – в Windows. Локальные адреса сайта всегда начинаются с префикса ‘FEC0:...’ и исполь- зуются для взаимодействий между компьютерами, составляющими еди- ный сайт (например, все компьютеры в подсети). В этом случае поле scopeid определяет числовой идентификатор сайта. В случае отсутствия необходимости указывать значения полей flowinfo и scopeid адреса IPv6 можно указывать в виде кортежа (host, port), как и адреса IPv4. Модуль socket 589 AF_UNIX При использовании сокетов домена UNIX адрес определяется как строка, содержащая путь в файловой системе, например: ‘/tmp/myserver’. AF_PACKET При использовании протокола пакетов в Linux адрес определяется, как кортеж (device, protonum [, pkttype [, hatype [, addr]]]), где в поле device передается строка, определяющая имя устройства, такая как “eth0”, а в поле protonum – целое число, указывающее номер протокола ethernet, как определено в заголовочном файле Константа Описание PACKET_HOST Пакет, предназначенный для локального компьютера. PACKET_BROADCAST Широковещательный пакет физического уровня. PACKET_MULTICAST Пакет физического уровня для многоадресной передачи. PACKET_OTHERHOST Пакет, предназначенный для другого компьютера, который был перехвачен драйвером устройства, действующим в ре- жиме прослушивания (promiscuous). PACKET_OUTGOING Пакет, исходящий из локального компьютера, который через петлевой интерфейс был передан пакетному сокету. В поле hatype передается целое число, указывающее тип аппаратного адре- са, используемого протоколом ARP, как определено в заголовочном файле . В поле addr передается строка байтов с аппаратным адре- сом, структура которого определяется значением поля hatype. Для ethernet в поле addr передается строка с аппаратным адресом, состоящим из 6 бай- тов. AF_NETLINK При использовании протокола Netlink в Linux адрес определяется, как кортеж (pid, groups), где в обоих полях pid и groups передаются целые числа без знака. Поле pid – это индивидуальный адрес сокета; поле обычно содер- жит идентификатор процесса, создавшего сокет, или 0, если соединение устанавливается с ядром. Поле groups – это битная маска, определяющая группу связанных адресов. За дополнительной информацией обращайтесь к описанию протокола Netlink. AF_BLUETOOTH Вид адресов протоколов семейства Bluetooth определяется конкретным ис- пользуемым протоколом. Для протокола L2CAP адрес определяется как кортеж (addr, psm), где в поле addr передается строка, такая как ‘01:23:45:67: 89:ab’ , а в поле psm – целое число без знака. Для протокола RFCOMM адрес 590 Глава 21. Работа с сетью и сокеты определяется как кортеж (addr, channel), где в поле addr передается строка адреса, а в поле channel – целое число. Для протокола HCI адрес определя- HCI адрес определя- адрес определя- ется как кортеж (deviceno,), где в поле deviceno передается целочисленный номер устройства. Для протокола SCO адрес определяется как строка host. Константа BDADDR_ANY представляет любой адрес и имеет строковое значе- ние ‘00:00:00:00:00:00’. Константа BDADDR_LOCAL имеет строковое значение ‘00:00:00:ff:ff:ff’ AF_TIPC Для семейства TIPC адрес определяется как кортеж (addr_type, v1, v2, v3 [, scope]) , где во всех полях передаются целые числа без знака. Поле addr_ type может принимать одно из следующих значений, которые также могут передаваться в полях v1, v2 и v3: Тип адреса Описание TIPC_ADDR_NAMESEQ v1 – тип сервера, v2 – идентификатор порта и v3 – число 0. TIPC_ADDR_NAME v1 – тип сервера, v2 – младший номер порта и v3 – старший номер порта. TIPC_ADDR_ID v1 – узел, v2 – ссылка и v3 – число 0. Необязательное поле scope может иметь одно из следующих значений: TIPC_ZONE_SCOPE , TIPC_CLUSTER_SCOPE или TIPC_NODE_SCOPE. Функции Ниже перечислены функции, которые определяются модулем socket: create_connection(address [, timeout]) Устанавливает соединение типа SOCK_STREAM с адресом address и возвращает уже подключенный объект сокета. В аргументе address передается кортеж вида (host, port). Необязательный аргумент timeout определяет предельное время ожидания. Эта функция сначала вызывает функцию getaddrinfo() и затем пытается соединиться с каждым из возвращаемых ею адресов. fromfd(fd, family, socktype [, proto]) На основе целочисленного дескриптора файла fd создает объект сокета. В остальных аргументах предаются семейство адресов, тип сокета и но- мер протокола, которые могут принимать те же значения, что и в функции socket() . Дескриптор файла должен ссылаться на ранее созданный объект сокета. Возвращает экземпляр класса SocketType. getaddrinfo(host, port [, family [, socktype [, proto [, flags]]]]) Используя информацию host и port о хосте, эта функция возвращает спи- сок кортежей с информацией, необходимой для открытия соединения. В аргументе host передается строка с именем хоста или IP-адрес в число- IP-адрес в число- -адрес в число- вой форме. В аргументе port передается число или строка, представляю- щая имя службы (например, “http”, “ftp”, “smtp”). Каждый из возвращае- Модуль socket 591 мых кортежей содержит пять элементов (family, socktype, proto, canonname, sockaddr) . Поля family, socktype и proto могут принимать те же значения, ко- могут принимать те же значения, ко- принимать те же значения, ко- принимать те же значения, ко- те же значения, ко- те же значения, ко- же значения, ко- же значения, ко- значения, ко- значения, ко- , ко- ко- торые передаются функции socket(). В поле canonname возвращается строка, представляющая каноническое имя хоста. В поле sockaddr возвращается кортеж с адресом сокета, как описывалось в предыдущем разделе, где опи- сываются способы адресации. Например: >>> getaddrinfo(“www.python.org”,80) [(2,2,17,’’,(‘194.109.137.226’,80)), (2,1,6,’’,(‘194.109.137.226’),80))] В этом примере функция getaddrinfo() вернула информацию о двух воз- можных соединениях. Первый кортеж в списке соответствует соединению по протоколу UDP (proto=17), а второй – соединению по протоколу TCP (proto=6). Чтобы сузить набор доступных адресов, можно использовать до- полнительный аргумент flags функции getaddrinfo(). Например, в следую- щем примере возвращается информация об установленном соединении по протоколу IPv4 TCP: >>> getaddrinfo(“www.python.org”,80,AF_INET,SOCK_STREAM) [(2,1,6,’’,(‘194.109.137.226’,80))] Чтобы определить все доступные соединения для указанного семейства адресов, можно использовать специальную константу AF_UNSPEC. Например, в следующем примере выполняется запрос всех возможных адресов TCP, который может возвращать информацию как для версии IPv4, так и для версии IPv6: >>> getaddrinfo(“www.python.org”,”http”, AF_UNSPEC, SOCK_STREAM) [(2,1,6,’’,(‘194.109.137.226’,80))] Функция getaddrinfo() предназначена для широкого применения и может применяться ко всем поддерживаемым сетевым протоколам (IPv4, IPv6 и так далее). Используйте эту функцию, если вас беспокоит проблема со- вместимости и поддержки протоколов, которые могут появиться в буду- щем, особенно если предполагается, что программа будет поддерживать протокол IPv6. getdefaulttimeout() Возвращает предельное время ожидания в секундах для сокетов. Значение None указывает, что предельное время ожидания не было определено. getfqdn([name]) Возвращает полностью квалифицированную версию доменного имени name . Если функция вызывается без аргумента, она возвращает информа- цию о локальном компьютере. Например, вызов getfqdn(“foo”) мог бы вер- нуть строку “foo.quasievil.org”. gethostbyname(hostname) Преобразует имя хоста, такое как ‘www.python.org’, в адрес IPv4. IP-адрес возвращается в виде строки, такой как ‘132.151.1.90’. Эта функция не под- держивает адреса IPv6. gethostbyname_ex(hostname) 592 Глава 21. Работа с сетью и сокеты Преобразует имя хоста в адрес IPv4, но возвращает кортеж (hostname, aliaslist, ipaddrlist) , где в поле hostname возвращается основное имя хоста, в поле aliaslist возвращается список альтернативных имен хоста для того же адреса, а в поле ipaddrlist – список адресов IPv4 для того же интерфейса на том же компьютере. Например, вызов gethostbyname_ex(‘www.python.org’) может вернуть примерно такой результат: (‘fang.python.org’, [‘www.python. org’], [‘194.109.137.226’]) . Эта функция не поддерживает адреса IPv6. gethostname() Возвращает имя хоста локального компьютера. gethostbyaddr(ip_address) Возвращает ту же информацию, что и функция gethostbyname_ex(), по ука- занному IP-адресу, такому как ‘132.151.1.90’. Если в аргументе ip_address пе- редать адрес IPv6, такой как ‘FEDC:BA98:7654:3210:FEDC:BA98:7654:3210’, функ- ция вернет информацию, относящуюся к этому адресу IPv6. |