Что такое дескриптор сокета
Перейти к содержимому

Что такое дескриптор сокета

12. Что такое дескриптор сокета?

Вы знаете, что при создании сокета сетевой адрес не указывается. Функция socket создает сокет и возвращает значение дескриптора, присвоенного системой этому сокету. Дескриптор указывает на член системной таблицы дескрипторов, соответствующий данному сокету.

Системная таблица дескрипторов управляется реализацией сокетов. Вам, как прикладному программисту, приходится общаться с этой таблицей посредством дескрипторов сокетов. На самом деле «создание сокета» — это просто процесс отведения памяти системой для размещения в ней структуры данных, описывающей данный сокет.

В операционной системе UNIX каждый процесс владеет одной таблицей дескрипторов файлов. (Вы помните, что разработчики интерфейса сокетов использовали ту же концепцию и для сетевого ввода-вывода.) Функция-socket в UNIX получает дескриптор из таблицы дескрипторов файлов. Дескриптор является указателем на внутреннюю структуру данных. Структура данных сокета в упрощенном виде показана на рис. .1.

Рис. 1

Как видно из рисунка, структура данных сокета включает элементы для хранения аргументов, с которыми была вызвана функция socket. Кроме того, в структуре размещены четыре адреса: локальный IP-адрес, удаленный IP-адрес, адреса локального и удаленного портов. Каждый раз, когда программа вызывает функцию-socket, реализация сокетов отводит машинную память для новой структуры данных, а затем размещает в ней семейство адресов, тип сокета и протокола. В таблице дескрипторов размещается указатель на эту структуру. Дескриптор, полученный вашей программой от функции socket, является индексом (порядковым номером) в таблице дескрипторов.

Интерфейс сокетов не определяет никаких способов управления дескриптором сокета. Сам UNIX обращается с дескрипторами сокетов точно так же, как с дескрипторами файлов. Другие приложения могут обращаться с дескрипторами так, как это им заблагорассудится. Другими словами, то, что происходит с данными, на которые указывает дескриптор, зависит от конкретной реализации системы, с которой вы работаете. Вам, как прикладному программисту, не обязательно знать подробности, касающиеся таблиц дескрипторов, структуры данных в них и отведения памяти. Мы рассматриваем все это, только чтобы показать, каким образом сокету присваивается сетевой адрес. Функция socket образует структуру данных сокета, не заполняя при этом поля адресов. Чтобы связать сокет с определенным сетевым адресом, необходимо вызвать другие функции, входящие в состав API, так, как это будет показано в следующих разделах.

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

Сетевой уровень IP идентифицирует сетевые компьютеры при помощи сетевого адреса. Это значит, что каждый компьютер, подключенный к Интернет, должен иметь уникальный сетевой адрес. Ранее объяснялось, как транспортный уровень использует адреса портов для обозначения определенных приложений (процессов) в сетевом компьютере. Каждый сетевой процесс, таким образом, использует номер порта сетевого компьютера в качестве собственного адреса. Наконец, вы знаете, что программы Интернет должны использовать семейство протоколов TCP/IP для передачи своих данных по сети. Таким образом, соединение между двумя сетевыми программами несет в себе следующую информацию:

— местный (локальный) порт протокола, обозначающий программу или процесс, посылающий сообщения или датаграммы;

— адрес локального компьютера, обозначающий сетевой компьютер, принимающий пакеты данных;

— удаленный порт протокола, обозначающий программу или процесс-получатель данных;

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

Структура данных сокета, как видно на рис. 1, соответствующая дескриптору сокета, содержит информацию об этих же пяти пунктах. Таким образом, сокет является реализацией абстрактной модели конечной точки сетевого соединения. Структура данных сокета содержит все элементы, необходимые конечной точке сетевого соединения. Структура данных сокета значительно упрощает процесс сетевого соединения. Когда одна программа желает установить связь с другой, программа-передатчик просто отдает свою информацию сокету, а интерфейс сокетов в свою очередь передает ее дальше стеку сетевых протоколов TCP/IP. Перед этим программа должна создать сокет, вызвав системную функцию-сокет, а затем сконфигурировать его, пользуясь функциями, также входящими в интерфейс сокетов. В следующих разделах будет показано, каким образом сокет конфигурируется.

Что такое дескриптор сокета

Эта глава описывает средства GNU для межпроцессорной связи, используя гнезда.

Гнездо — обобщенный межпроцессорный канал связи. Подобно каналу, гнездо представляется как дескриптор файла. Но, в отличие от каналов, гнезда поддерживает ссылка между несвязанными процессами, и даже между процессами, выполняющимися на различных машинах, которые связываются по сети. Гнезда — первичный способ связи с другими машинами; telnet, rlogin, ftp, переговоры, и другие сетевые программы используют гнезда.

Не все операционные системы поддерживают гнезда. В библиотеке GNU, заглавный файл ‘sys/socket.h’ существует независимо от операционной системы, и функции гнезд всегда существуют, но если система действительно не поддерживает гнезда, эти функции всегда терпят неудачу.

Незавершенность: Мы в настоящее время не описали средства для передачи сообщений или для конфигурирования интерфейса Internet.

  • Каковы модули передачи данных? Некоторые стили связи расценивают данные как последовательность байтов, без большей структуры; другие группируют байты в записи (которые известны в этом контексте как пакеты).
  • Могут данные быть потеряны в течение нормальной операции? Некоторые стили связи гарантируют, что все посланные данные прибывают в порядке, как они были посланы (страховка системы или сетевых сбоев); другие стили иногда теряют данные как нормальная часть операции, и могут иногда поставлять пакеты больше чем один раз или в неправильном порядке.
  • Является ли ссылка полностью с одним партнером? Некоторые стили связи — подобно телефонному звонку, Вы делаете соединение с одним отдаленным гнездом, и тогда свободно обмениваетесь данными. Другие стили — подобно отправке по почте символов, Вы определяете адрес адресата для каждого сообщения, которое Вы посылаете.

В заключение Вы должны выбрать протокол, чтобы установить связь. Протокол определяет какой механизм низкого уровня используется, чтобы передавать и получить данные. Каждый протокол допустим для определенного именного пространства и стиля связи; именное пространство иногда называется совокупностью протоколов из-за этого имена именных пространств начинаются с ‘PF_’.

  • Чтобы иметь связь между двумя гнездами, они должны определить тот же самый протокол.
  • Каждый протокол значим со специфическим стилем/именным пространством и не может использоваться с несоответствующими комбинациями. Например, TCP протокол удовлетворяет только стилю связи потока байтов и именному пространству Internet.
  • Для каждой комбинации стиля и именного пространства, имеется заданный по умолчанию протокол, который Вы можете запрашивать, определяя 0 как номер протокола. И это — то, что Вы должны обычно делать — использовать значение по умолчанию.

Библиотека GNU поддерживает различные виды сокетов. В этом разделе описываются различные типы сокетов предоставляемые в бибилотекой GNU. Упомянутые в данном разделе символические константы определены в «sys/socket.h».

Более подробное описание работы с использованием этого типа Вы найдете в Разделе 11.8 [Соединения].

Каждый раз когда Вы пишите данные в сокет этого типа, данные становятся одним пакетом. Вы должны определить адрес получателя для каждого пакета.

Единственной гарантией, которую предоставляет Вам система относительно запросов передачи данных, является то, что она пробует наилучшим образом посылать каждый пакет. У нее может получится посылка шестого пакета после неудачи с четвертыми и пятыми пакетами; седьмой пакет может прибыть перед шестым, также второй может прибыть как раз после шестого.

Типичное использование типа SOCK_DGRAM в ситуациях, где есть возможность повторной посылки пакетов, если ответ не был получен в приемлемое время.

Имя сокета обычно называется адресом. Функции и символы для имеющихся адресов сокетов могли называться как с использованием термина, так и использованием термина «адрес». Вы можете расценивать эти термины как синонимичные в контексте обсуждения сокетов.

Сокет, созданный при помощи функции socket, не имеет никакого адреса. Другие процессы могут использовать его для связи только после того как Вы дадите ему адрес. Мы называем это — связывание адреса с сокетом. Связывание происходит при помощи функции bind.

В первый раз, когда Вы посылаете данные из сокета, или используете его, чтобы инициализировать соединение, система назначает адрес автоматически.

Подробности адресации сокетов изменяются, в зависимости от именного пространства, которое Вы используете. См. Раздел 11.4 [Именное пространство Файла], или Раздел 11.5 [Именное пространство Internet].

Независимо от именного пространства, Вы используете те же самые функции bind и getsockname, чтобы установить и исследовать адрес гнезда.

Форматы Адреса

Функции bind и getsockname используют обобщенный тип данных struct sockaddr *, чтобы представить указатель на адрес гнезда. Вы не можете использовать этот тип данных действительно, чтобы интерпретировать адрес или создавать его; для этого, Вы должны использовать соответствующий тип данных для именного пространства гнезда.

Таким образом, обычная нужно создать адрес в соответствующем именном пространстве специфического типа, и приводить указатель на struct sockaddr *, когда Вы вызываете bind или getsockname.

Единственная информация, которую Вы можете получить из структуры sockaddr — указатель формата адреса, который сообщает Вам какой тип данных использовать, чтобы понять адрес полностью.

Символы в этом разделе определены в заголовочном файле «sys/socket.h».

Каждый формат адреса имеет символическое имя, которое начинается с «AF_ «. Каждый из них соответствует «PF_ » символу, который обозначает соответствующее именное пространство. Вот список названий форматов адресов: AF_FILE

Обозначает формат адреса, который идет с именным пространством файла. (PF_FILE — имя этого именного пространства.) См. Раздел 11.4.2 [Подробности Именного пространства Файла], для уточнения информации относительно этого формата адреса.

Это синоним AF_FILE, для совместимости. (PF_UNIX ­ аналогично синоним для PF_FILE.)

Обозначает формат адреса, который идет в именном пространстве Internet. (PF_INET — имя этого именного пространства.) См. Раздел 11.5.1 [Формат Адреса Internet].

Не обозначает никакой специфический формат адреса. Он используется только в редких случаях, когда необходимо очистить снаружи заданный по умолчанию адрес адресата от «соединенного» датаграмного сокета. См. Раздел 11.9.1 [Посылка Датаграмм]. Соответствующий символ указателя именного пространства PF_UNSPEC существует для законченности, но нет никакой причины использовать его в программе.

«Sys/socket.h» определяет символы, начинающиеся с » AF_ » для различных видов сетей, большинство из которых фактически не встречается. Мы будем документировать только то, что действительно используется на практике.

Установка Адреса сокета

Используйте функцию bind, чтобы для связывания адреса сокета. Прототип для bind находится в заголовочном файле «sys/socket.h». Для примеров использования см. Раздел 11.4 [Именное пространство Файла].

Возвращаемое значение — 0 при успехе и -1 при отказе. Для этой функции в переменной errno определены следующие виды ошибок: EBADF

аргумент — не допустимый описатель файла. ENOTSOCK

дескриптор socket — сокет. EADDRNOTAVAIL

заданный адрес не доступен на этой машине. EADDRINUSE

Существует другой сокет использующий заданный адрес.

сокет уже имеет адрес. EACCESS

Вам не достаточно прав для обращения к запрошенному адресу. (В области Internet, только супер-пользователю позволяют определить номер порта в диапазоне от 0 до IPPORT_RESERVED минус один; см. Раздел 11.5.3 [Порты].) Дополнительные условия могут быть возможны в зависимости от специфического именного пространства сокета.

Чтение Адреса сокета

Используйте функцию getsockname, чтобы исследовать адрес гнезда Internet. Прототип для этой функции находится в заголовочном файле «sys/socket.h».

Формат данных адреса зависит от именного пространства сокета. Длина информации обычно устанавливается для данного именного пространства, так что обычно Вы можете знать точно, сколько места необходимо. Обычно нужно зарезервировать место для значения, используя соответствующий тип данных для именного пространства сокета, и тогда привести адрес к struct sockaddr *, чтобы передать его getsockname.

Возвращаемое значение — 0 при успехе и -1 при ошибке. Для этой функции в переменной errno определены следующие виды ошибок: EBADF

аргумент socket — не допустимый описатель файла. ENOTSOCK

дескриптор socket — не сокет. ENOBUFS

не имеется достаточных внутренних буферов, доступных для операции.

Вы не можете читать адрес сокета в именном пространстве файла. Это непротиворечиво с остальной частью системы; вообще, не существует способа найти имя файла из описателя для этого файла.

Этот раздел описывает подробности именного пространства файла, чье символическое имя (требуется, когда Вы создаете сокет) ­ PF_FILE.

Понятия Именного пространства Файла

В именном пространстве файла, адреса сокетов — имена файлов. Вы можете определять любое желаемое имя файла для адреса сокета, но Вы должны иметь право записи в каталоге, содержащем его. Для чтобы соединяться с сокетом, Вы должны иметь право чтения для него. Обычно эти файлы помещаются в каталог `/tmp’.

Одна особенность именного пространства файла — имя используется только при открытии соединения; если только оно было законченно, адрес не значим и может не существовать.

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

После того, как Вы закрываете сокет в именном пространстве файла, Вы должны удалить имя файла из файловой системы. Используйте unlink или remove, чтобы делать это; см. Раздел 9.5 [Удаление Файлов].

Именное пространство файла поддерживает только один протокол для любого типа связи; 0 — номер протокола.

Подробности Именного пространства Файла

Чтобы создавать сокет в именном пространстве файла, используйте константу PF_FILE как аргумент именного пространства для socket или socketpair. Эта константа определена в «sys/socket.h».

Структура для определения имен сокетов в именном пространстве файла определена в заголовочном файле «sys/un.h»:

Незавершенность: Почему — 108? RMS предлагает делать его массивом нулевой длины и использовать alloc, чтобы зарезервировать соответствующее количество памяти, основываясь на длине filename.

Вы должны вычислить параметр длины для адреса сокета в именном пространстве файла как сумму размера компоненты sun_family и длины (не размера резервирования!) строки имени файла.

Пример файлового-именного пространства сокетов

Вот пример, показывающий, как создавать и связывать сокет в именном пространстве файла.

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

Чтобы создать сокет в именном пространстве Internet, используйте символическое имя PF_INET этого именного пространства как аргумент именного пространства socket или socketpair. Эта макрокоманда определена в «sys/socket.h».

  • Адрес машины с которой Вы хотите соединяться. Адреса в Internet могут быть определены разными способами; эти способы обсуждаются в Разделе 11.5.1 [Формат Адреса Internet] Разделе 11.5.2 [Главные Адреса], и Разделе 11.5.2.4 [Главные Имена].
  • Номер порта для машины. См. Раздел 11.5.3 [Порты].

Формат Адреса сокета Internet

В именном пространстве Internet, адрес состоит из главного адреса и порта на этой главной ЭВМ. Кроме того, протокол, который Вы выбираете, служит как бы частью адреса, потому что местные числа порта значимы только внутри специфического протокола.

Тип данных для представления адресов в именном пространстве Internet определен в заголовочном файле «netinet/in.h».

Когда Вы вызываете bind или getsockname, Вы должны определить sizeof (struct sockaddr_in) как параметр длины при использовании адреса в именном пространстве Internet.

Главные Адреса

Каждый компьютер в Internet имеет один, или большое количество Internet адресов, т. е. числа, которые идентифицируют этот компьютер среди остальных на Internet. Пользователи обычно записывают число-адрес главной ЭВМ как последовательность из четырех чисел, отделяемых точками, например «128.52.46.32».

Каждый компьютер также имеет одно или большое количество главных имен, которые являются строками слов, отделяемых точками, например «churchy.gnu.ai.mit.edu».

Программы, которые допускают пользователю определять главную ЭВМ обычно принимают и числовые адреса и главные имена. Но для открытия соединения программе необходим числовой адрес, так что для использования главного имени, Вам нужно преобразовать его в числовой адрес.

Адреса Главной ЭВМ Internet

Адрес главной ЭВМ в Internet — это номер, содержащий четыре байта данных. Они разделены на две части, сетевой номер и местный номер внутри этой сети. Сетевой номер состоит из первых одного, двух или трех байт; остальная часть байтов — местный адрес.

Сетевые числа зарегистрированы в Сетевом Информационном Центре (NIC), и разделены на три класса A, B, и C. Местные числа сетевого адреса индивидуальных машин зарегистрированы администратором в локальной сети.

Сеть класса А имеет одиночно-байтовые числа в диапазоне от 0 до 127. Сетей класса A не так уж много, но каждая из них может поддерживать очень большое количество главных ЭВМ. Сети класса В размера имеет Двух-байтовые сетевые числа, с первым байтом в диапазоне от 128 до 191. Класс C самый маленький; адреса в нем они имеют Трех-байтовые сетевые числа, с первым байтом в диапазоне 192-255. Таким образом, первый 1, 2, или 3 байты адреса Internet определяют сеть. Оставшиеся байты адреса Internet определяют адрес внутри этой сети.

Нулевая сеть класса A зарезервирована для передачи по всем сетям. Кроме того, главный номер 0 внутри каждой сети зарезервирован для передачи на все главные ЭВМ в этой сети.

127-ая сеть класса A зарезервирована для возврата цикла; Вы можете всегда использовать адрес Internet «127.0.0.1», чтобы обратиться к главной машине.

Так как одиночная машина может быть элементом нескольких сетей, она может иметь много адресов главной ЭВМ Internet. Однако, предполагается, что существует не более одной машины с тем же самым главным адресом.

  1. а.b.c.d определяет все четыре байта адреса индивидуально.
  2. а.b.c последняя часть адреса, интерпретируется как 2-байтовое число. Это полезно для определения главных адресов в сети класса B с сетевым адресом a.
  3. а если дана только одна часть, то она соответствует непосредственно числу главного адреса.
  4. «0x» или «0X» подразумевает шестнадцатеричную систему счисления; «0» подразумевает восьмеричную; в противном случае десятичная система счисления.

Тип Данных Главного Адреса

Адреса главной ЭВМ Internet представляются в некоторых контекстах как integers (long unsigned int). В других контекстах, integer упакован внутри структуры типа struct in_addr. Было бы лучше, если бы использование было сделано непротиворечивым.

Следующие базисные определения для Internet адреса, появляются в файле «netinet/in.h»:

Функции Главного Адреса

Это дополнительные функции для управления Internet адресацией, объявленые в «arpa/inet.h». Они представляют Internet адреса в сетевом порядке байтов; это сетевые числа и числа локальных сетевых адресов в главном порядке байтов. См. Раздел 11.5.5 [Порядок Байтов], для объяснения сетевого и главного порядка байтов.

Главные Имена

Кроме стандарта числа-и-точки для Internet адреса, Вы можете также обратиться к главной ЭВМ символическим именем. Преимущество символического имени — то, что его обычно проще запомнить. Например, машина с адресом «128.52.46.32» также может иметь адрес «churchy.gnu.ai.mit.edu»; и другие машины в этом домене могут обратиться к ней просто как «churchy».

Система использует базу данных, чтобы следить за отображением между главными именами и главными числами. Эта база данных — файл, обычно «/etc/hosts» или эквивалент, обеспеченный блоком преобразования имен. Функции и другие символы для доступа к этой базе данных объявлены в «netdb.h». Возможности BSD могут использоваться при подключении файла «netdb.h».

В главной базе данных каждый адрес только блок памяти h_length байт длиной. Но в других контекстах имеется неявное предположение, что Вы можете преобразовывать его в struct addr_in или long unsigned int. Главные адреса в структуре struct hostent всегда даны в сетевом порядке байтов; см. Раздел 11.5.5 [Порядок Байт].

Вы можете использовать gethostbyname или gethostbyaddr, для уточнения инфрмации базы данных главных ЭВМ относительно специфической главной ЭВМ. Информация возвращена в статически размещенной структуре.

Если происходит сбой поиска, gethostbyaddr возвращает пустой указатель.

Если поиск имени gethostbyname или gethostbyaddr окончился неудачно, Вы можете выяснить причину, рассматривая значение переменной h_errno. (Было бы правильнее установить errno, но использование h_errno совместимо с другими системами.) Перед использованием h_errno, Вы должны объявить его примерно так:

Вы можете также просматривать всю базу данных главных ЭВМ используя sethostent, gethostent, и endhostent. Будьте внимательны при использовании этих функций, потому что они не допускают повторного использования.

Если аргумент stayopen является отличным от нуля, она устанавливает флаг так, чтобы последующие обращения к gethostbyname или gethostbyaddr не закрыли базу данных (что они обычно сделали бы).

Это делается для эффективности, если Вы вызываете эти функции несколько раз, то избегаете повторного открытия базы данных для каждого обращения.

Порты Internet

Адрес сокета в именном пространстве Internet состоит из адреса Internet машины плюс номер порта, который отличает гнездо на данной машине (для данного протокола). Номера портов располагаются от 0 до 65535.

Номера портов меньше, зарезервированых IPPORT_RESERVED для стандартных серверов, типа finger и telnet. Имеется база данных, которая следит за ними, и Вы можете использовать функцию getservbyname для отображения сервисного номера порта; см. Раздел 11.5.4 [База данных Услуг].

Если Вы собираетесь устанавливать сервер, который не является стандартно определенным в базе данных, то Вам необходимо выбрать для него номер порта. Используйте номера большие чем IPPORT_USERRESERVED; такие числа зарезервированы для серверов и никогда не будут генерироваться системой.

Когда Вы используете сокет без определения адреса, система генерирует номер порта для него. Этот номер попадает в интервал между IPPORT_RESERVED и IPPORT_USERRESERVED.

На Internet, фактически, законно иметь два различных сокета с одинаковыми номерами портов, пока они оба не попытаются связаться с тем этим адресом сокета (главный адрес плюс номер порта). Вы не должны дублировать номер порта за исключением специальных обстоятельств, где протокол с более высоким уровнем требует этого. Обычно, система не будет разрешать Вам делать это; bind требует различные номера портов. Чтобы многократно использовать номер порта, Вы должны установить опцию сокета SO_REUSEADDR. См. Раздел 11.11.2 [Опции Сокетов].

Эти макрокоманды определены в заголовочном файле «netinet/in.h».

База данных Услуг

База данных, которая следит за «общеизвестными» услугами — это обычно или файл «/etc/services» или эквивалент из блока преобразования имен. Вы можете использовать эти утилиты, объявленные в «netdb.h» для обращения к базе данных услуг.

Пустой указатель завершает массив.

Чтобы получать информацию относительно специфического обслуживания, используйте функции getservbyname или getservbyport функции. Информация возвращается в статически размещенной структуре.

Эта функция полезна как для серверов так и для клиентов; серверы используют ее, чтобы определить, на каком порту они должны принимать пакеты (см. Раздел 11.8.2 [Прием]).

Вы можете также просматривать базу данных услуг, используя setservent, getservent, и endservent. Будьте внимательным в использовании этих функций, потому что они не предназначены для повторного использования.

Если аргумент stayopen является отличным от нуля, она устанавливает флаг так, чтобы последующие обращения к getservbyname или getservbyport не закрыли базу данных (поскольку они обычно закрыли бы). Это делается для большей эффективности, если Вы вызываете эти функции несколько раз, избегая повторного открытия базы данных для каждого обращения.

Преобразование Порядка Байтов

Различные виды компьютеров используют различные соглашения для упорядочения байтов внутри слова. Некоторые компьютеры помещают старший байт сначала (это называется «big-endian» порядком), а другие помещают его последним («little-endian» порядок).

Так, чтобы машины с различными соглашениями порядка байтов могли связываться, протоколы Internet определяют каноническое соглашение порядка байтов для данных, переданных по сети. Оно известно как сетевой порядок байта.

При установлении соединения в Internet, Вы должны удостовериться, что данные в sin_port и sin_addr элементах структуры sockaddr_in представляются в сетевом порядке байта. Если Вы кодируете данные integer в сообщениях, посланных через сокет, Вы должны преобразовать их в сетевой порядок байта. Если Вы не делаете этого, ваша программа может работать не правильно при сообщении с другими типами машин.

Если Вы используете getservbyname и gethostbyname или inet_addr, для получения номера порта и главного адреса, то эти значения уже в сетевом порядке байта, и Вы можете копировать их непосредственно в структуру sockaddr_in.

Иначе, Вы должны преобразовать значения явно. Используйте htons и ntohs, чтобы преобразовать значения для sin_port элемента. Используйте htonl и ntohl, чтобы преобразовать значения для sin_addr элемента. (Помните, struct in_addr эквивалентен long unsigned int.) Эти функции описаны в «netinet/in.h».

База данных Протоколов

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

Заданный по умолчанию протокол связи для именного пространства Internet зависит от стиля связи. Для потокового взаимодействия, значение по умолчанию — TCP («протокол управления передачей»). Для датаграмной связи, значение по умолчанию — UDP («протокол датаграммы пользователя»). Для надежной датаграмной связи значение по умолчанию — RDP («надежный датаграмный протокол»). Вы должны почти всегда использовать это значение по умолчанию.

Протоколы Internet вообще определены именем вместо номера. Сетевые протоколы, которые знает главная ЭВМ, сохранены в базе данных. Она обычно происходит от файла «/etc/protocols», или может быть эквивалент, обеспеченный блоком преобразования имен. Вы можете искать номер протокола, связанный с именованным протоколом в базе данных, используя getprotobyname функцию.

Имеются детализированные описания утилит для доступа к базе данных протоколов. Они объявлены в «netdb.h».

Последний элемент массива — пустой указатель.

Вы можете использовать getprotobyname и getprotobynumber, чтобы искать в базе данных протоколов специфический протокол. Информация возвращается в статически размещенной структуре; Вы должны копировать информацию, если Вы хотите сохранить ее для следующих обращений.

Вы можете также просматривать целую базу данных протоколов (по одному протоколу одновременно), используя setprotoent, getprotoent, и endprotoent. Будьте внимательным в использовании этих функций, потому что они не предназначены для повторного использования.

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

Пример Internet сокета.

Вот пример, показывающий, как создавать и называть сокет в именном пространстве Internet. Созданный сокет существует на машине, на которой выполняется программа. Вместо поиска и использования адреса Internet машины, этот пример определяет INADDR_ANY как главный адрес.

Конечно другие именные пространства и связанные семейства протоколов также реализованы, но не описаны здесь, потому что они редко используются. PF_NS обращается к протоколам Программного обеспечения Сети Ксерокса (Xerox Network Software). PF_ISO замещает Открытые системы Связи (Open Systems Interconnect). PF_CCITT обращается к протоколам из МККТТ (CCITT). «Socket.h» определяет эти символы и другие протоколы.

PF_IMPLINK используется для связи между главными ЭВМ и Процессорами Сообщений Internet.

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

Создание сокета.

Примитив для создания сокета — функция socket, объявлена в «sys/socket.h».

Возвращаемое значение из socket — описатель файла для нового сокета, или -1 в случае ошибки. Следующие errno условия ошибки определены для этой функции: EPROTONOSUPPORT

Протокол или стиль не обеспечивается заданным именным пространством.

EMFILE процесс имеет слишком много открытых описателей файла.

система имеет слишком много открытыми описателей файла

процесс не имеет привилегии, чтобы создать сокет заданного стиля или протокола.

в системе закончилось внутреннее пространство буфера. Описатель файла, возвращенный функцией socket поддерживает и чтение и запись. Но, подобно трубопроводам, сокеты не поддерживают операции позиционирования файла.

Пример вызова функции socket см. Раздел 11.4 [Именное пространство Файла].

Закрытие сокета.

Когда Вы закончили использование сокета, Вы можете просто закрыть описатель файла примитивом close; см. Раздел 8.1 [Открытие и Закрытие Файлов].

Вы можете также выключать только прием или только передачу на соединении, вызывая shutdown, которая объявлена в «sys/socket.h».

socket — не допустимый описатель файла. ENOTSOCK

socket — не сокет. ENOTCONN

socket не соединен.

Пары сокетов

Пара socket состоит из пары соединенных (но неименованных) сокетов. Это очень похоже на трубопровод и используется аналогичным способом. Пары сокетов создаются функцией socketpair, описание в файле «sys/socket.h».

Аргументы namespace, style и protocol интерпретируется как в функции socket. style должен быть один из стилей связи, перечисленных в Разделе 11.2 [Стили связb]. Аргумент именного пространства определяет именное пространство, которое должно быть AF_FILE (см. Раздел 11.4 [Именное пространство Файла]); protocol определяет протокол связи.

Если style определяет стиль связи без установки логического соединения, то два сокета, которые Вы получаете, не соединены, строго говоря, но каждое из них знает другое как заданный по умолчанию адрес адресата, так что они могут посылать пакеты друг другу.

Функция Socketpair возвращает 0 при успехе и -1 при отказе. В переменной errno определяются следующие коды ошибок для этой функции: EMFILE

Процесс имеет слишком много открытых описателей файла. EAFNOSUPPORT

Не обеспечивается заданное именное пространство. EPROTONOSUPPORT

Не обеспечивается заданный протокол. EOPNOTSUPP

Заданный протокол не поддерживает создание пар сокетов.

  • Раздел 11.8.1 [Соединение], описывает то, что клиентская программа должна делать, чтобы инициализировать соединение с сервером.
  • Раздел 11.8.2 [Прием], и Раздел 11.8.3 [Принятие Соединений], описывает то, что программа сервера должна делать, чтобы ждать и делать после запросов соединения от клиентов.
  • Раздел 11.8.5 [Пересылка Данных], описывает, как данные перемещаются через соединенные сокеты.

Создание Соединения

В создании соединения, клиент делает соединение, в то время как сервер ждет и принимает соединение. Здесь мы обсуждаем то, что клиентская программа должна делать, используя функцию connect, которая объявлена в «sys/socket.h».

Обычно, connect ждет, пока сервер не отвечает на запрос прежде. Вы можете устанавливать режим неблокирования на сокете socket, чтобы заставить connect возвратиться немедленно без ожидания ответа. См. Раздел 8.10 [Флаги Состояния Файла], для уточнения инфрмации относительно неблокирования.

Нормальное возвращаемое значение connect — 0. Если происходит ошибка, connect возвращает -1. В переменной errno определяются следующие коды ошибок для этой функции: EBADF

сокет socket — не допустимый описатель файла.

указанный сокет — не сокет.

заданный адрес не доступен на отдаленной машине.

именное пространство addr не обеспечивается этим сокетом.

указанный сокет уже соединен.

попытка установить соединение не состоялась.

сервер активно отказался устанавливать соединение.

сеть данного addr не доступна с этой главной ЭВМ.

адрес сокета для данного addr уже используется.

указанный сокет не-блокируемый, и соединение не могло бы быть установлено немедленно.

указанный сокет не-блокируемый и уже имеет отложенное соединение.

Ожидание Соединений

Теперь рассмотрим то, что процесс сервера должен делать, чтобы принять соединение из сокета. Это включает использование функции listen, чтобы дать возможность запросам на соединения через сокет, и позже использование функции accept (см. Раздел 11.8.3 [Принятие Соединений] ) чтобы действовать по запросу. Функция listen используется только для уже установленного логического соединения.

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

В именном пространстве Файла, обычные биты защиты файла управляют доступом к сокету.

Аргумент n определяет длину очереди для отложенных соединений.

Функция listen возвращает 0 при успехе и -1 в случае неудачи. В переменной errno определяются следующие коды ошибок для этой функции: EBADF

аргумент socket — не допустимый описатель файла.

аргумент socket — не сокет.

указанный сокет не поддерживает эту операцию.

Принятие Соединений

Когда сервер получает запрос соединения, он может создать соединение, принимая запрос. Для этих целей следует использовать функцию accept.

Сокет, который был установлен как сервер, может принимать запросы соединения от многих клиентов. Этот сокет сервера не станет частью соединения; взамен, accept делает новый сокет, который разделяет соединения. Accept возвращает описатель для этого сокета.

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

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

Функция accept находится в состоянии ожидания, когда нет возможности принять соединение, если, конечно, указанный сокет не имеет набор режимов неблокирования. (Вы можете использовать select, чтобы ждать отложенное соединение на неблокируемом сокете.) См. Раздел 8.10 [Флаги Состояния Файла], для уточнения информации относительно режима неблокирования.

Аргументы Addr и length_ptr используется, чтобы возвратить информацию относительно имени клиентского сокета, которое инициализировало соединение. См. Раздел 11.3 [Адреса сокетов], для уточнения информации относительно формата.

Сокет, который был установлен как сервер не станет частью соединения; взамен, accept сделает новый сокет. Accept возвращает описатель для этого сокета. Нормальное возвращаемое значение accept — описатель файла для нового сокета.

После accept, первоначально указанный сокет остается открытым и не связанным, и продолжает ожидать, пока Вы не закрываете его. Вы можете принимать дальнейшие соединения с этим сокетом, вызывая accept снова.

Если происходит ошибка, и accept возвращает -1. В переменной errno определяются следующие коды ошибок для этой функции: EBADF

аргумент socket — не допустимый описатель файла.

дескрипторный аргумент socket — не сокет.

описанный сокет не поддерживает эту операцию.

сокет имеет набор режимов неблокирования, и нет никаких отложенных соединений. Функцию accept не позволяется применять для сокета без установления логического соединения.

Кто соединен со Мной?

См. Раздел 11.3 [Адреса Сокетов] , для уточнения информации относительно формата адреса. В некоторых операционных системах, getpeername работает только для сокетов в области Internet.

Возвращаемое значение — 0 при успехе и -1 в случае неудачи. В переменной errno определяются следующие коды ошибок для этой функции: EBADF

аргумент socket — не допустимый описатель файла.

указанный сокет — не сокет.

указанный сокет не соединен.

нет внутренних доступных буферов.

Пересылка Данных

Если сокет был соединен с равным, Вы можете использовать обычные примитивы read и write (см. Раздел 8.2[Примитивы ввода — вывода]), чтобы передать данные. Сокет — канал двусторонней связеи, так что чтение и запись может выполняться в оба конца.

Имеются также некоторые режимы ввода — вывода, которые являются специфическими для операций с сокетами. Чтобы определять эти режимы, Вы должны использовать функции recv и send вместо более обобщенного чтения и записи. Функции recv и send берут дополнительный аргумент, который Вы можете использовать, чтобы определить различные флаги, для управления специальными режимами ввода — вывода. Например, Вы можете определить флаг MSG_OOB, чтобы читать или писать внепоточные данные, а также флаги MSG_PEEK или MSG_DONTROUTE.

Посылка Данных

Функция send объявлена в файле «sys/socket.h». Если ваш аргумент flags нуль, Вы можете точно также использовать write вместо send. Если сокет был соединен, но соединение прервано, Вы получаете сигнал SIGPIPE для каждого использования send или write (см. Раздел 21.2.6 [Разнообразные Сигналы]).

Эта функция возвращает число переданных байтов, или -1 в противном случае. Если сокет неблокируемый, то send (подобно write) может возвращать после посылки только часть данных. См. Раздел 8.10 [Флаги Состояния Файла], для уточнения информации относительно режима неблокирования.

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

аргумент socket — не допустимый описатель файла.

операция был прервана сигналом прежде, чем любые данные были посланы. См. Раздел 21.5 [Прерванные Примитивы].

указанный сокет — не сокет.

тип сокетаа требует, чтобы сообщение было послано быстро, но сообщение слишком большое для этого.

на сокете был установле режим неблокирования, а операция записи блокирует. (Обычно send блокирует, пока операция не может быть завершена.)

не имеется достаточного внутреннего доступного пространства буфера.

Вы не соединили этот сокет.

Этот сокет был соединен, но соединение теперь разбито. В этом случае send генерирует SIGPIPE сначала; если этот сигнал игнорируется или блокируется, или если обработчик возвращается, то происходит сбой send с EPIPE.

Получение Данных

Функция recv объявлена в файле «sys/socket.h». Если ваш аргумент flags является нулем, Вы можете точно также использовать read вместо recv; см. Раздел 8.2 [Примитивы ввода-вывода].

Если режим неблокирования установлен для сокета, и никакие данные не доступны для чтения, recv не ожидает, а сразу возвращает код ошибки. См. Раздел 8.10 [Флаги Состояния Файла], для уточнения информации относительно режима неблокирования.

Эта функция возвращает число полученных байтов, или -1 в противном случае. В переменной errno определяются следующие коды ошибок для этой функции: EBADF

аргумент socket — не допустимый описатель файла.

дескриптор socket — не сокет.

Режим неблокирования был установлен на сокете. (Обычно, recv блокирует пока не имеется входа, доступного для чтения.)

операция была прервана сигналом прежде, чем любые данные прочитались. См. Раздел 21.5 [Прерванные Примитивы].

Вы не соединили этот сокет.

Опции Данных сокета.

Аргумент flags для send и recv — битовая маска. Вы можете объединить значения следующих макрокоманд вместе (через OR), чтобы получить значение для этого аргумента. Все они определены в файле «sys/socket.h».

Пример сокета с потоком байтов.

Вот пример программы клиента, которая устанавливает соединение для сокета в пространстве Internet с поточным типом передачи данных. Она не делает ни чего особенно интересного; если она соединилась с сервером, она посылает текстовую строку серверу и выходит.

Пример соединения сервера (Тип соединения — поток байтов)

Текст программы сервера намного более сложен. Так как мы хотим предоставлять многим клиентам быть соединенными с сервером, но в то же самое время, было бы неправильно ждать ввод от одиночного клиента, просто вызывая read или recv. Взамен, нужно использовать select (см. Раздел 8.6 [Ждущий ввод — вывод] ), чтобы ждать ввод на всех открытых сокетах. Это также позволяет серверу иметь дело с дополнительными запросами соединения.

Этот специфический сервер не делает хоть что-нибудь интересное, если он получил сообщение от клиента, то он закрывает сокет клиента по получению признака конца файла.

Эта программа использует make_socket и init_sockaddr для устанавления адреса сокета; см. раздел 11.5.7 [Inet Пример].

Данные Вне потока

Потоки с соединениями разрешающими данные вне потока имеют приоритет выше, чем обычные данные. Обычно причина для посылки данных вне потока — исключительные условия. Способ послать данные вне потока использует send с флагом MSG_OOB (см. Раздел 11.8.5.1 [Посылка Данных]).

Данные вне потока посылаются с высшим приоритетом, плюс процесс получения не обрабатывает их в обыкновенное очереди, но чтобы читать доступные данные вне потока следует использовать recv с флагом MSG_OOB (см. Раздел 11.8.5.2 [Получение Данных]). Обычные операции чтения не воспринимают данные вне потока; они читают только обычные данные.

Когда сокет находит, что данные вне потока продвигаются, он посылает сигнал SIGURG процессу владельца или группе процессов сокета. Вы можете определять владельца, используя команду F_SETOWN для функции fcntl; см. Раздел 8.12 [Ввод Прерывания]. Вы должны также установить обработчик для этого сигнала, как описано в Главе 21 [Обработка Сигналов], для соответствующего действия типа чтения данных вне потока.

В качестве альтернативы, Вы можете проверять задержать данные вне потока, или ждать данные вне потока, при использовании функции select; она может ждать исключительное условие на гнезде. См. Раздел 8.6 [Ждущий ввод — вывод].

Уведомление о данных вне потока (с SIGURG или с select) обозначает, что данные вне потока находятся в пути; данные не могут фактически прибывать позже. Если Вы пробуете читать данные вне потока прежде, чем они ппребывают, то recv генерирует ошибку с кодом EWOULDBLOCK.

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

Этот раздел описывает, как использовать стили связи, которые не используют соединения (стили SOCK DGRAM и SOCK_RDM). При использовании этих стилей, Вы группируете данные в пакеты, и каждый пакет — независимая связь. Вы определяете адресата для каждого пакета индивидуально.

Датаграмные пакеты подобны письмам: Вы посылаете каждый независимо, с собственным адресом адресата, и они могут прибывать в неправильном порядке или вообще не прибывать.

Функции listen и accept не предназначены для сокетов, использующих стили связи без установки логического соединения.

Посылка Датаграмм

Нормальный способ посылки данных относительно датаграмного сокета использует функцию sendto, объявленную в «sys/socket.h».

. Вы можете вызывать connect на датаграмном сокете, но эта функция определяет заданного по умолчанию адресата для дальнейшей пе­ редачи данных на сокете. Когда сокет имеет по умолчанию заданного ад­ ресата, Вы можете использовать send (см. Раздел 11.8.5.1 [Посылка Дан­ ных] ) или write (см. Раздел 8.2 [Примитивы ввода — вывода] ) для по­ сылки пакетов. Вы можете отменять заданного по умолчанию адресата, вы­ зывая connect, и используя формат адреса AF_UNSPEC в аргументе addr. См. Раздел 11.8.1 [Соединение].

Flags интерпретируется также как и в send; см. Раздел 11.8.5.3 [Опции данных сокетов].

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

Также возможно, что для одного обращения к sendto она сообщит ошибку из-за проблемы связанной с предыдущим обращением.

Получение Датаграмм

Функция recvfrom читает пакет из датаграмного сокета и также сообщает Вам, откуда он был послан. Эта функция объявлена в «sys/socket.h».

Аргумент size определяет максимальное число байтов, которые нужно читать.

Если пакет является больше чем size байт, то, Вы получаете первые size байт пакета, а остальная часть пакета потеряна. Не существует способа прочитать остальную часть пакета. Таким образом, когда Вы используете протокол пакетов, Вы должны всегда знать длину ожидаемого пакета.

Аргументы addr и length_ptr используются для возвращения адреса источника пакета. См. Раздел 11.3 [Адреса сокетов]. Для сокета в области файла, информация адреса не будет значима, так как Вы не можете читать адрес такого сокета (см. Раздел 11.4 [Именное пространство Файла] ). Вы можете определять пустой указатель как аргумент addr, если Вы не заинтересованы в этой информации.

Flags интерпретируется тем же самым способом как recv (см. Раздел 11.8.5.3 [Опции Данных сокета]). Возвращаемое значение и условия ошибки — такие же как для recv.

Вы можете использовать recv (см. Раздел 11.8.5.2 [Получение Данных]) вместо recvfrom, если знаете, что не должны выяснить, кто послал пакет. Даже read, может использоваться, если Вы не хотите определять flags (см. Раздел 8.2 [Примитивы ввода ­ вывода]).

Датаграмный Пример сокета.

Вот набор примеров программ, которые посылают сообщения используя датаграмный стиль. И клиент и сервер используют функцию make_named_socket, которая была предоставлена в Разделе 11.4 [Именное пространство Файла], для создания и связывания сокетов.

Сначала программа сервера. Очевидно, это не особенно полезная программа, но она показывает общие идеи.

Пример Чтения Датаграмм

Вот программа клиента, соответствующая серверу выше.

Она посылает датаграмму серверу и ждет ответ. Обратите внимание, что сокету клиента (также как для сервера) в этом примере должно быть дано имя. Так, чтобы сервер мог направлять сообщение обратно клиенту. Так как сокет не имеет никакого связанного состояния соединения, единственый способ, которым сервер может сделать это ссылаясь на имя клиента.

Мы объяснили выше, как написать программу сервера, которая реализует собственное ожидание. Такой сервер должен уже выполниться для любого соединения с ним.

Другой способ обеспечивать обслуживание портов для Internet состоит в том, чтобы использовать в программе для ожидания демона inetd. Inetd — программа, которая выполняется все время и ждет (используя select) сообщения на заданном наборе портов. Когда она получает сообщение, она принимает соединение (если стиль сокета запрашивает соединение), и тогда запускает дочерний процесс, чтобы выполнить соответствующую программу сервера. Вы определяете порты и их программы в файле «/etc/inetd.conf».

Inetd Серверы

Написание программы сервера, которая будет выполнена inetd очень просто. Каждый раз когда кто-то запрашивает соединение с соответствующим портом, стартует новый процесс сервера. Соединение уже существует в это время; гнездо доступно как описатель стандартного ввода и как описатель стандартного вывода (описатели 0 и 1) в процессе сервера. Так что программа сервера может начинать читать и писать данные сразу же. Часто программа нуждается только в обычных средствах ввода-вывода; фактически, универсальная программа-фильтр, которая не знает ничего относительно сокетов, может работать как сервер потока байтов, запускаемая inetd.

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

Конфигурирование inetd

Файл «/etc/inetd.conf » сообщает inetd, какие порты ожидает какой сервер для обработки пакетов. Обычно каждый вход в файле — это строка, но Вы можете разбивать его на много строк, если все, кроме первой строки входа, начинаются с пропуска. Строки, которые начинаются с «*» являются комментариями.

Имеются два стандартных входа в «/etc/inetd.conf»:

style и protocol определяют стиль связи и протокол для использования ожидающего сокета. Стиль должен иметь имя стиля связи, преобразованного в строчные буквы и с удаленным «SOCK_», например, «stream» или «dgram». Протокол должен быть один из протоколов, перечисленных в «/etc/protocols». Типичные имена протокола — «tcp» для соединений потока байтов и «udp» для ненадежных датаграмм.

Поле wait должно быть, или «wait» или «nowait». «wait» используется, если стиль не требует установления логического соединения и обрабатывает многократные запросы. «nowait» используется, когда необходимо,чтобы inetd начинал новый процесс для каждого сообщения, или запроса, который приходит. Если используется соединение, то wait должен быть «nowait».

user — имя пользователя, под которым сервер должен выполняться. Inetd выполняется под пользователя root, так что она может устанавливать ID пользователей дочерних процессов произвольно. Лучше избегать использования «root» для пользователя; но некоторые серверы, типа Telnet и FTP, читают username и пароль самостоятельно. Эти серверы должны быть запущены под пользователя root изначально, так как они могут регистрировать потоки данных передаваемых по сети.

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

Первое слово в аргументах — нуль, который должен быть именем программы непосредственно (каталоги sans).

Если Вы редактируете «/etc/inetd.conf», то Вы можете указывать необходимость повторного чтения файла для inetd и сообщения нового содержимого, посылая inetd сигнал SIGHUP. Вы будете должны использовать ps, чтобы определить ID процесса inetd, поскольку оно не фиксировано.

Этот раздел описывает, как читать или установить различные опции, которые изменяют поведение сокетов и их основных протоколов связи.

Когда Вы манипулируете опциями сокета, Вы должны определить, к какому уровню они относятся, то есть применяется ли опция к интерфейсу сокета, или к интерфейсу протокола связи низшего уровня.

Функции Опций сокета.

Имеются функции для исследования и изменения опций сокета. Они объявлены в «sys/socket.h».

Значение опции сохранено в буфере, на который указывает optval. Перед обращением, Вы должны обеспечить в * optlen_ptr размер этого буфера; по возвращении, он содержит число байтов информации, фактически сохраненной в буфере.

Большинство опций интерпретирует буфер optval как одиночное значение int.

Фактически возвращаемое значение getsockopt — 0 при успехе и -1 в случае неудачи. В переменной errno отражены следующие возможные причины: EBADF

аргумент socket — не допустимый описатель файла.

дескриптор socket — не сокет.

Optname не имеет смысла для данного уровня.

Возвращаемое значение и коды ошибки для setsockopt такие же как для getsockopt.

Опции уровня сокета.

Вот таблица имен опций уровня сокета; все они определены в файле «sys/socket.h».

Значение имеет тип int; значение отличное от нуля означает «да».

Много систем приходят с базой данных, которая записывает список сетей, известных разработчику системы. Она обычно сохраняется или в файле «/etc/networks» или в блоке преобразования имен. Эта база данных полезна для маршрутизации программ типа route, но бесполезна для программ, которые просто связываются по сети. Функции предназначенные для обращения к этой базе данных описаны в «netdb.h «.

Он имеет следующие элементы:

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

Сокеты

Какие бы замечательные идеи в области телекоммуникаций, распределенных баз знаний или поисковых систем вам не пришли в голову, реализовать их на практике можно, лишь написав соответствующую программу. Основные операционные среды (Unix или Windows ) базируются в настоящее время на идеологии сокетов ( socket ). Эта технология была разработана в университете г. Беркли (США) для системы Unix, поэтому соединители (сокеты) иногда называют сокетами Беркли (berkeley sockets). Сокеты реализуют механизм взаимодействия не только партнеров по телекоммуникациям, но и процессов в ЭВМ вообще (см. [2.15], а также http://book.itep.ru/7/sock_71.htm). Технология сокетов лежит в основе современного сетевого программирования.

Работа с сокетами содержит ряд этапов: сокет создается, настраивается на заданный режим работы, применяется для организации обмена и, наконец, ликвидируется. Технология сокетов поддерживает работу с любыми стеками протоколов, совмещенные процедуры ввода/вывода, использование большого числа сервис-провайдеров (серверов услуг), возможность группирования сокетов, что позволяет реализовать их приоритетное обслуживание, и многое другое. Набор операторов, поддерживающих интерфейс сервис провайдера, образует отдельную динамическую библиотеку.

Для общей синхронизации работы сервис-провайдеров и приложений в winsock введено понятие объектов событий. Объекты событий служат, в частности, для организации работы совмещенных по времени процессов информационного обмена. Здесь уместно замечание об использовании стандартных номеров портов. В многозадачных, многопользовательских системах стандартные номера портов используются при инициализации процесса. Так как допускается несколько идентичных соединений (например, несколько одновременных сессий FTP ) между клиентом и сервером, стандартными номерами портов здесь не обойтись. Ведь PsIPs сервера могут соответствовать несколько PcIPc клиента.

В системах, ориентированных на соединение, пара комбинаций IP -адресов и номеров портов однозначно определяет канал связи между двумя процессами в ЭВМ. Такая комбинация называется сокетом ( socket ). Номера портов могут и совпадать, так как относятся к разным машинам, но IP -адреса должны быть обязательно разными. Впервые идея сокета была использована в системе BSD4.3 Unix для организации сетевого ввода/вывода. В Unix внешнее устройство и файл с точки зрения системного программиста эквивалентны. Сетевые процедуры несколько сложнее и не укладываются в такую простую схему. Из этой схемы выпадают, прежде всего, операции , при которых сервер пассивно ожидает обращения, особенно операции обмена, не ориентированные на соединение. Сокет является пограничным понятием между протоколами телекоммуникаций и операционной системой ЭВМ. Сокеты играют важную роль при написании прикладных программ ( API ).

Сокет отправителя = IP-адрес отправителя + номер порта отправителя

Сокет адресата = IP-адрес адресата + номер порта адресата

При обменах, ориентированных на соединение, формируется ансамбль ( IPSPS + IPDPD ), где IPSPS — адрес и порт отправителя, а IPDPD – адрес и порт места назначения.

Межкомпьютерные коммуникации не сводятся к знакомству с соседским депозитарием, к выполнению операций Telnet/ssh, FTP /scp и т.д. Одной из важнейших задач является удаленный контроль за процессами в больших распределенных системах, когда обмен информацией активизируется не человеком, а ЭВМ. Примерами таких задач могут служить управление современными высокотехнологичными производствами, сбор метео-­ или другой геофизической информации в реальном масштабе времени, эксперименты в области физики высоких энергий, где для контроля установки и сбора экспериментальных данных используются десятки (а иногда и сотни) вычислительных машин, которые обмениваются диагностической информацией и данными. Именно для решения таких задач и применяются идеи сокетов, «труб» и т.д.. Понятие сокета в прикладных программах — это не просто комбинация IP -адресов и номеров портов, это указатель на структуру данных, где хранятся параметры виртуального канала. Прежде чем воспользоваться сокетом, его нужно сформировать. Оператор формирования сокета имеет вид:

s=socket(INT AF, INT type, INT protocol);

где все параметры целочисленные, AF (address_family) характеризует набор протоколов, соответствующий данному сокету (это может быть набор Internet , Unix, Appletalk и т.д.). Для Интернет AF может принимать только значение PF_INET , для Unix PF_UNIX . Аргумент type определяет тип коммуникаций ( SOCK_STREAM , SOCK_RAW , и SOCK_DGRAM ). Аргумент protocol задает код конкретного протокола из указанного набора (заданного AF ), который будет реализован в данном соединении. Протоколы обозначаются символьными константами с префиксом IPPROTO_ (например, IPPROTO_TCP или IPPROTO_UDP ). Допускается значение protocol=0 (протокол не указан), в этом случае используется значение по умолчанию для данного вида соединений. Значения AF и type можно обычно найти в файле <sys/ socket .h>. Возвращаемый параметр S представляет собой дескриптор сокета. Параметр SOCK_STREAM говорит о том, что вы намерены создать надежный двунаправленный канал обмена, ориентированный на соединение ( TCP для Интернет ). Связь с другим процессом в этом случае устанавливается оператором connect . После установления соединения данные могут посылаться оператором send или получаться посредством оператора recv. Параметр SOCK_DGRAM характеризует канал, не ориентированный на соединение, с пакетами фиксированного размера (например, UDP в случае AF= PF_INET ). Такой канал позволяет использовать операторы sendto и recvfrom . Параметр SOCK_RAW определяет третий режим, при котором возможно использование протоколов нижнего уровня, например, ICMP или даже IP . Таким образом, формирование сокета — это создание описывающей его структуры данных.

Если операция socket завершилась успешно, s равно дескриптору сокета, в противном случае s=INVALID_SOCKET (1) . С помощью оператора WSAGetLastError можно получить код ошибки , проясняющий причину отрицательного результата.

Дескриптор сокета указывает на элемент таблицы дескрипторов, соответствующий данному сокету. Оператор socket отводит место в этой таблице. Элемент такой таблицы имеет вид:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *