Одна из возможных конфигураций программных гнезд
Допустимые комбинации протоколов и драйверов задаются
при конфигурации системы
- во время работы системы менять нельзя
По духу организация программных гнезд близка к идее
потоков
Но менее гибкая схема
- не допускает изменения конфигурации "на
ходу"
Взаимодействие процессов основано на модели "клиент-сервер"
- процесс-сервер "слушает (listens)"
свое программное гнездо
- процесс-клиент пытается общаться с процессом-сервером
через другое программное гнездо
- ядро поддерживает внутренние соединения и маршрутизацию
данных от клиента к серверу
Программные гнезда с общими коммуникационными свойствами,
такими как способ именования и протокольный формат адреса, группируются
в домены
- "домен системы UNIX"
для процессов, которые взаимодействуют через программные гнезда
в пределах одного компьютера
- "домен Internet"
для процессов, которые взаимодействуют в сети в соответствии с
семейством протоколов TCP/IP
Два типа программных гнезд
- с виртуальным соединением (stream sockets)
- дейтаграммные гнезда (datagram sockets)
Виртуальные соединения:
- передача данных от клиента к серверу в виде непрерывного
потока байтов с гарантией доставки
- до начала передачи данных должно быть установлено
соединение
Дейтаграммные программные гнезда:
- не гарантируют абсолютной надежной, последовательной
доставки сообщений и отсутствия дубликатов дейтаграмм
- не требуется предварительное установление соединений
По умолчанию обеспечивается подходящий протокол
для каждой допустимой комбинации "домен-гнездо"
- TCP для виртуальных соединений
- UDP для дейтаграммного способа коммуникаций
Создание нового программного гнезда:
sd = socket(domain, type,
protocol);
- domain
- домен гнезда
- type - тип (с
виртуальным соединением или дейтаграммное)
- protocol - желаемый
сетевой протокол
- sd - дескриптор
программного гнезда
Закрытие (уничтожение) гнезда
close(sd)
Связывание ранее созданного программного гнезда
с именем:
bind(sd, socknm, socknlen);
- sd
- дескриптор ранее созданного программного гнезда
- socknm - адрес
структуры, которая содержит имя (идентификатор) гнезда, соответствующее
требованиям домена данного гнезда и используемого протокола
- для домена системы UNIX имя является именем объекта в файловой
системе
- при создании программного гнезда создается файл
- socknlen - длина
в байтах структуры socknm
Запрос связи с существующим программным гнездом
со стороны процесса-клиента:
connect(sd, socknm, socknlen);
- смысл параметров, как у функции bind
- имя программного гнезда на другой стороне коммуникационного
канала
- у гнезда с дескриптором sd
и у гнезда с именем socknm
должны быть одинаковые домен и протокол
- если тип гнезда с дескриптором sd
- дейтаграммный, то connect
служит для информирования системы об адресе назначения пакетов,
которые в дальнейшем будут посылаться с помощью функции send
Информирования о том, что процесс-сервер планирует
установление виртуальных соединений через указанное гнездо:
listen(sd, qlength);
- qlength
- максимальная длина очереди запросов на установление соединения,
которые должны буферизоваться системой, пока их не выберет процесс-сервер
Выборка процессом-сервером очередного запроса на
установление соединения с указанным программным гнездом служит
функция accept:
nsd = accept(sd, address, addrlen);
- sd
- дескриптор существующего программного гнезда, для которого ранее
была выполнена функция listen
- address
- массив данных, в который должна быть помещена информация, характеризующая
имя программного гнезда клиента
- addrlen
- адрес, по которому находится длина массива address
- выполнение функции приводит к установлению виртуального
соединения
- nsd
- новый дескриптор программного гнезда, который должен использоваться
при работе через данное соединение
- по адресу addrlen
помещается реальный размер массива данных, которые записаны по
адресу address
Передача и прием данных через программные гнезда
с установленным виртуальным соединением:
count = send(sd, msg, length,
flags);
count = recv(sd, buf, length,
flags);
В send:
- msg
указывает на буфер с данными, которые требуется послать
- length
- длина этого буфера
- flags
== MSG_OOB
внеочередная посылка данных
В recv:
- buf
указывает на буфер, в который следует поместить принимаемые данные
- length
- максимальная длина этого буфера
- flags
== MSG_PEEK
перепись сообщения в пользовательский буфер без его удаления
из системных буферов
Вместо send
и recv
можно использовать read
и write
- выполняются аналогично send
и recv
Для посылки и приема сообщений в дейтаграммном
режиме:
count = sendto(sd, msg,
length, flags, socknm, socknlen);
count = recvfrom(sd, buf,
length, flags, socknm, socknlen);
- смысл параметров sd,
msg,
buf
и lenght
аналогичен смыслу одноименных параметров функций send
и recv
- socknm
и socknlen
функции sendto
задают имя программного гнезда, в которое посылается сообщение
- могут быть опущены, если до этого вызывалась
функция connect
- параметры socknm
и socknlen
функции recvfrom
позволяют серверу получить имя пославшего сообщение процесса-клиента
Немедленная ликвидация установленного соединения:
shutdown(sd, mode);
- немедленно остановить коммуникации
- со стороны посылающего процесса
- со стороны принимающего процесса
- с обеих сторон
- в зависимости от значения параметра mode
shutdown отличаются
от close:
- выполнение close
последней "притормаживается" до окончания попыток системы
доставить уже отправленные сообщения
- shutdown разрывает
соединение, но не ликвидирует дескрипторы ранее соединенных гнезд
- для ликвидации требуется вызов close