Опубликован: 28.09.2007 | Доступ: свободный | Студентов: 5798 / 810 | Оценка: 4.20 / 4.10 | Длительность: 47:32:00
ISBN: 978-5-94774-707-2
Лекция 4:

Сокеты

Возможная схема использования сокетов в случае работы N клиентов с одним WEB-сервером показана на рис. 4.1. Клиент 1 сформировал два соединения с сервером.

Формирование сокетов при подключении к одному WEBсерверу

Рис. 4.1. Формирование сокетов при подключении к одному WEBсерверу

Схема взаимодействия различных операторов winsock в рамках идеологии клиент/сервер для случая процедур, ориентированных на соединение, показана на рисунке 4.2. Горизонтальными стрелками обозначены направления посылки сетевых сообщений.

Следует иметь в виду, что программе клиента (выделена рамкой) в этом режиме не нужно знать номер порта, поэтому она не обращается к процедуре bind, а для установления связи сразу вызывает оператор connect. Современные распределенные информационные системы, WWW-серверы, поисковые системы и т.д. эффективно используют механизмы формирования сокетов и многие процедуры, описанные в данном разделе. Из литературы [2.15, 2.24] известно, что для многих видов услуг в Интернет выделены строго определенные номера портов. Доступ же к этим услугам должен быть обеспечен достаточно большому числу пользователей. С клиентской стороны при этом используются номера портов со значениями из диапазона 1024-5000. Для каждого нового клиентского запроса в ЭВМ-сервере, как правило, формируется новый процесс.

Схема взаимодействия операторов winsock для процедур, ориентированных на соединение

Рис. 4.2. Схема взаимодействия операторов winsock для процедур, ориентированных на соединение

Лишь при успешной реализации всех перечисленных операций может начаться обмен данными. Для пересылки информации могут использоваться команды write, read, send, recv. Команды write и read имеют форму вызова:

R=write(s, buf, len) или R=read(s, buf, len),

где sдескриптор сокета, buf — имя массива, подлежащего пересылке (или предназначенного для приема), lenдлина этого массива. Оператор writev отличается от write тем, что данные могут не лежать в виде непрерывного массива:

R=writev(s, io_vect, vectlen) или R=readv(s, io_vect, vectlen),

где sдескриптор сокета, io_vectвектор указатель на список указателей, vectlenдлина списка указателей. Команда выполняется медленнее, чем write или read. Список указателей имеет формат (рис. 4.3):

Формат списка указателей для функций readv и writev

Рис. 4.3. Формат списка указателей для функций readv и writev

Команды send(s, msg_buf, buflen, flags) и recv имеют аналогичный формат, но среди параметров обращения содержат переменную flags, которая служит для целей диагностики и управления передачей данных (например, пересылка информации с высоким приоритетом ( MSG_OOB — Message Out Of Band ), что используется, в частности, при передаче звуковых сообщений). При работе с операторами send или recv надо быть уверенным, что принимающая сторона знает, что ей следует делать с этими приоритетными сообщениями. Другой возможный флаг, определяемый константой MSG_PEEK, позволяет анализировать запросы из входной очереди транспортного уровня. Обычно после считывания данных из входной очереди они уничтожаются. Когда MSG_PEEK=1, данные из входной очереди не стираются. Этот флаг используется, например, программой FTP. При успешном выполнении команды будет возвращено число переданных байтов, в противном случае —1.

Все перечисленные выше операторы рассчитаны на применение в рамках протоколов, ориентированных на установление соединения (TCP), где не требуется указание адреса места назначения. В протоколах типа UDP (не ориентированных на соединение) для передачи информации используются операторы sendto, recvfrom или sendmsg:

R=sendto(s, msg_buf, buflen, flags, adr_struc, adr_struc_len)

или recvfrom(s, msg_buf, buflen, flags, adr_struc, adr_struc_len),

где sдескриптор сокета, msg_bufуказатель на буфер, где лежит сообщение, buflenдлина этого буфера (длина сообщения), adr_struc — адресная структура, содержащая исчерпывающую информацию об адресате, adr_struc_lenдлина этой структуры. Оператор recvfrom принимает все данные, приходящие на его порт. Приняв дейтограмму, recvfrom записывает также адрес, откуда эта дейтограмма получена. Сервер может посылать по этому адресу дейтограмму­-отклик. Вызов оператора sendmsg имеет форму:

R=sendmsg(s, msg_struc, flags) [или recvmsg(s, msg_struc, flags)],

где sдескриптор сокета, msg_struc — информационная структура, формат которой показан ниже на рисунке 4.4. Применение структур делает программирование пересылки сообщений более гибким. Следует учитывать, что для обменов, не ориентированных на соединение, сокет как бы состоит лишь из одной половины (IP-адрес и номер порта). Сокеты, созданные однажды для обмена (UDP), далее могут жить своей жизнью. Они могут принимать пакеты от других аналогичных "сокетов" и сами посылать им дейтограммы (кавычки здесь связаны с тем, что это не реальный сокет и никакого соединения здесь не осуществляется).

Формат информационной структуры msg_struc

Рис. 4.4. Формат информационной структуры msg_struc

Взаимодействие операторов winsock для систем, не ориентированных на соединение, показано на рисунке 4.5. Здесь так же, как и в случае, ориентированном на соединение, сервер вызывает socket и bind, после чего обращается к процедуре recvfrom (вместо read или recv ). Программа-клиент в данной схеме обращается к оператору bind и совсем не использует оператор connect (ведь предварительного соединения не нужно). Для передачи запросов и приема откликов здесь служат операторы sendto и recvfrom, соответственно.

Помимо уже описанных операторов для работы с сокетами имеется еще один — select, довольно часто используемый серверами. Оператор select позволяет процессу отслеживать состояние одного или нескольких сокетов. Для каждого сокета вызывающая программа может запросить информацию о статусе read, write или error. Форма обращения имеет вид:

Схема взаимодействия операторов winsock для процедур, не ориентированных на соединение

Рис. 4.5. Схема взаимодействия операторов winsock для процедур, не ориентированных на соединение
R=select(num_of_socks, read_socks, write_socks, error_socks, max_time),

где num_of_socks — число контролируемых сокетов (в некоторых реализациях не используется и является необязательным; по умолчанию это число не должно превышать 64).

В версии Беркли read_socks, write_socks и error_socks представляют собой побитовые маски, определяющие тип сокета. Параметр read_socks — это указатель на структуру, описывающую набор сокетов, состояние которых проверяется на возможность чтения (версия winsock ). Если сокет находится в состоянии listen, он будет помечен как "готов для чтения", при условии, что запрос на соединение уже получен. Это предполагает выполнение оператора accept без блокировки. Для других сокетов "готовность к чтению" подразумевает наличие в очереди запросов чтения. Для сокетов типа SOCK_STREAM это означает, что виртуальный сокет, соответствующий данному сокету, закрылся и операторы recv или recvfrom будут выполнены без блокировки. Если виртуальное соединение закрыто корректно, оператор recv вернет код 0, в противном случае (например, принудительное закрытие) будет возвращен код WSAECONNRESET. Параметр write_socksуказатель на набор сокетов, состояние которых проверяется на возможность записи. Если сокет находится в процессе выполнения процедуры connect, "способность к записи" означает, что установление связи завершено. Для других сокетов это значит, что операции send или sendto будут выполнены без блокировки.

Параметр error_socks — это указатель на набор сокетов, проверяемых на ошибки. В некоторых реализациях этот аргумент идентифицирует список сокетов, помеченных как приоритетные. Сокет помечается как приоритетный, если опция SO_OOBINLINE=FALSE. В случае ошибки оператор select отмечает сокет, где это произошло. Select работает лишь с теми сокетами, которые были выделены с помощью масок. При успешном выполнении оператор возвращает число сокетов, готовых к операциям ввода/вывода, и модифицирует коды масок в соответствии с состоянием сокетов. Прикладная программа может использовать результаты вызова оператора select, анализируя полученные коды масок. Аргумент max_time определяет максимальное время, выделенное select для завершения своей работы. Для уточнения типа ошибки, возникшей при исполнении операции select, можно воспользоваться процедурой WSAGetLastError.

Другим важным оператором является closesocket(s), который закрывает канал сокета с одной из сторон. Все описанные выше операторы (кроме socket, bind и listen ) блокируют работу программы до своего завершения. Практически любая операция, непосредственно связанная с выполнением процедур ввода/вывода, может блокировать выполнение других прикладных функций winsock.

Для обслуживания прикладных процессов (например, WWW-сервера, работа с распределенными базами данных и пр.) разработано много других сервисных программ (WINSOCK.DLL), перечень которых представлен в таблице 4.1.

Большинство перечисленных команд имеют развитую систему диагностики, кроме того, во многих реализациях Unix существует много других полезных команд, описание которых вы можете найти в инструкциях по использованию системы Unix. Рассмотрим некоторые из них.

Программа ioctlsocket(s, long cmd, u_long FAR*argp) служит для получения параметров сокета (выполнение не зависит от типа протокола и коммуникационной субсистемы). Аргумент cmd представляет собой код команды, которая будет выполнена для сокета s, argpуказатель на параметр команды. Возможно применение команд: FIONBIO — разрешает/запрещает режим блокировки сокета s (команда WSAAsyncSelect ставит сокет в режим запрета блокировок автоматически); FIONREAD — определяет объем данных, которые могут быть автоматически считаны через сокет s ; SIOCATMARK — задает режим чтения приоритетной информации (для сокетов типа SOCK_STREAM ).

Таблица 4.1. Перечень служебных операторов для работы с сокетами (Беркли)
Имя команды назначение
getdomainname Возвращает имя домена
gethostbyname Возвращает IP-адрес для заданного сетевого имени
gethostname Возвращает имя ЭВМ (обычно имя ее домена)
gethostadr Возвращает IP-адрес ЭВМ
getnetaddr Возвращает адрес сети
getnetname Возвращает имя сети
getpeername Возвращает имя партнера, подключенного к сокету
getportbyname Возвращает имя и код протокола для указанного имени (например, ICMP, UDP или TCP)
getportbynumber Возвращает имя протокола для указанного его кода
getservbyname Извлекает из базы данных название протокола и номер порта для указанного имени сетевой услуги
getservbyport Возвращает имя сетевой услуги для заданного номера порта
getsockname Возвращает местный адрес (имя) сокета
getsockopt Запрашивает информацию о сокете
htonl Преобразует порядок байтов 32-разрядного кода из машинного в сетевой
htons Преобразует порядок байтов 16-разрядного кода из машинного в сетевой
inetaddr Преобразует символьную строку IP-адреса из десятично-точечного формата в 32-разрядный код с сетевым порядком байтов
inet ntoa Преобразует IP-адрес в десятично-точечный формат
ioctlsocket Управляет параметрами сокета, связанными с обработкой операций ввода/вывода
ntohl Преобразует порядок байтов 32-разрядного кода из сетевого в машинный
ntohs Преобразует порядок байтов 16-разрядных кодов из сетевого в машинный
ethostname Устанавливает имя ЭВМ
setsockopt Устанавливает опции сокета
shutdown Закрывает один из концов дуплексного канала для местной ЭВМ
socketpair Генерирует пару сокетов
Наталья Шульга
Наталья Шульга

Курс "информационная безопасность" .

Можно ли на него записаться на ПЕРЕПОДГОТОВКУ по данному курсу? Выдается ли диплом в бумажном варианте и высылается ли он по почте?

Мария Архипова
Мария Архипова