Сокеты, ориентированные на соединения, функционируют наподобие телефонного звонка: адреса запрашивающей и принимающей сторон фиксируются в самом начале, на этапе установки соединения.
■ При передаче дейтаграмм не гарантируется доставка и правильный порядок пакетов. Пакеты могут теряться и приходить в произвольном порядке. Операционная система лишь обещает сделать "все возможное".
Дейтаграммные сокеты функционируют подобно почтовой службе: отправитель указывает адрес получателя каждого сообщения и не контролирует доставку пакетов.
Пространство имен сокета определяет способ записи адресов. Например, в локальном пространстве имен адреса — это обычные имена файлов. В пространстве имен Internet адрес сокета состоит из IP-адреса компьютера, подключенного к сети, и номера порта. Благодаря номерам портов можно различать сокеты, созданные на одном компьютере.
Протокол определяет способ передачи данных. Основными семействами протоколов являются TCP/IP (ключевые сетевые протоколы, используемые в Internet) и AppleTalk (протоколы, используемые системами Macintosh). Сокеты могут также работать в соответствии с локальным коммуникационным протоколом UNIX. Не все комбинации типов взаимодействия, пространств имен и протоколов поддерживаются.
Сокеты являются более гибкими в управлении, чем рассмотренные выше механизмы межзадачного взаимодействия. При работе с сокетами используются следующие функции:
■ socket()
— создает сокет;
■ close()
— уничтожает сокет;
■ connect()
— устанавливает соединение между двумя сокетами;
■ bind()
— назначает серверному сокету адрес;
■ listen()
— переводит сокет в режим приема запросов на подключение;
■ accept()
— принимает запрос на подключение и создает новый сокет, который будет обслуживать данное соединение.
Сокеты представляются в программе файловыми дескрипторами.
Создание и уничтожение сокетов
Функции socket()
и close()
создают и уничтожают сокет соответственно. В первом случае необходимо задать три параметра: пространство имен, тип взаимодействия и протокол. Константы, определяющие пространство имен, начинаются с префикса PF_
(сокращение от "protocol family" — семейство протоколов). Например, константы PF_LOCAL
и PF_UNIX
соответствуют локальному пространству имен, а константа PF_INET
— пространству имен Internet. Константы, определяющие тип взаимодействия, начинаются с префикса SOCK_
. Сокетам, ориентированным на соединения, соответствует константа SOCK_STREAM
, а дейтаграммным сокетам — константа SOCK_DGRAM
.
Выбор протокола определяется связкой "пространство имен — тип взаимодействия". Поскольку для каждой такой пары, как правило, лучше всего подходит какой-то один протокол, в третьем параметре функции socket()
обычно задается значение 0 (выбор по умолчанию). В случае успешного завершения функция socket()
возвращает дескриптор сокета. Чтение и запись данных через сокеты осуществляется с помощью обычных файловых функций, таких как read()
, write()
и т.д. По окончании работы с сокетом его необходимо удалить с помощью функции close()
.
Вызов функции connect()
Чтобы установить соединение между двумя сокетами, следует на стороне клиента вызвать функцию connect()
, указав адрес серверного сокета. Клиент — это процесс, инициирующий соединение, а сервер — это процесс, ожидающий поступления запросов на подключение. В первом параметре функции connect()
задается дескриптор клиентского сокета, во втором— адрес серверного сокета, в третьем — длина (в байтах) адресной структуры, на которую ссылается второй параметр. Формат адреса будет разным в зависимости от пространства имен.
Передача данных
При работе с сокетами можно применять те же самые функции, что и при работе с файлами. О низкоуровневых функциях ввода-вывода, поддерживаемых в Linux, рассказывается в приложении Б, "Низкоуровневый ввод-вывод". Имеется также специальная функция send()
, являющаяся альтернативой традиционной функции write()
.
Жизненный цикл сервера можно представить так:
1) создание сокета, ориентированного на соединения (функция socket ());
2) назначение сокету адреса привязки (функция bind ());
3) перевод сокета в режим ожидания запросов (функция listen ());
4) прием поступающих запросов (функция accept ());
Читать дальше