- •Подсистема управления вводом-выводом
- •Int creat(const char *path, mode_t mode);
- •Int open(const char *path, int oflag, ...);
- •Int fildes;
- •Int close(int fildes);
- •Int fildes;
- •1.Взаимодействие драйверов с программной и аппаратной средой
- •10.3.4 Опрос терминала
- •2. Основы tcp/ip
- •2.1. Модуль ip создает единую логическую сеть
- •-----------------------------¬ --------------------------------¬
- •--------------------------------------------¬
- •Ip-сеть "development" ip-сеть "accounting"
- •223.1.2.1 Alpha
- •Int socket(int domain, int type, int protocol)
- •11.20. Процесс создает в домене "unix system" гнездо потокового
Int socket(int domain, int type, int protocol)
Функция socket() создает сокет, который используется для передачи данных. Дескриптор сокета (целое число), который возвращает функция socket(), аналогичен описателю файла. Он используется в операциях над данным сокетом и, более того, его можно использовать в качестве дескриптора файла в таких операциях как close(),read(),write(),fcntl()и др. Например, функцияclose()используется для того, чтобы удалить сокет.
Аргумент domainопределяет используемое семейство протоколов и должен иметь значениеAF_INET(семейство протоколов TCP/IP) илиAF_UNIX.
Аргумент typeтип передачи данных и может принимать следующие значения:
SOCK_DGRAM передача пакетов данных;
SOCK_STREAM поток данных.
При использовании протокола UDPаргумент type должен иметь значение SOCK_DGRAM, а при использовании протоколаTCP- значение SOCK_STREAM.
Аргумент protocol указывает используемый протокол и может принимать следующие значения :
IPPROTO_TCPпротоколаTCP.
IPPROTO_UDPпротоколаUDP;
0протокол выбирается ОС в соответствии со значениями аргументовdomainиtype
Рассмотрим следующие два примера вызова функции socket():
sd = socket(AF_INET, SOCK_DGRAM, 0)
sd = socket(AF_INET, SOCK_STREAM, 0)
В первом создается UDP-сокет, а во второмTCP-сокет.
Функция bind связывает дескриптор гнезда с именем:
bind(sd,address,length);
где sd - дескриптор гнезда, address - адрес структуры, определяю-
щей идентификатор, характерный для данной комбинации домена и
протокола (в функции socket). Length - длина структуры address;
без этого параметра ядро не знало бы, какова длина структуры,
поскольку для разных доменов и протоколов она может быть различ-
ной.
Пока процесс-сервер готовится к приему связи по виртуальному
каналу, ядру следует выстроить поступающие запросы в очередь на
обслуживание. Максимальная длина очереди задается с помощью сис-
темной функции listen:
listen(sd,qlength)
где sd - дескриптор гнезда, а qlength - максимально-допустимое
число запросов, ожидающих обработки.
---------------------¬ --------------------------¬
¦ Процесс-клиент ¦ ¦ Процесс-сервер ¦
¦ ¦ ¦ ¦ ¦ • ¦
¦ ¦ ¦ ¦ ------ •••••• ¦
¦ ¦ ¦ ¦ ¦ • ¦
¦ ¦ ¦ ¦listen addr accept addr¦
L---------+----------- L-----+------------•-------
¦ ¦ •
L---------------------------•••••••••••••
Рисунок 11.19. Прием вызова сервером
Системная функция accept принимает запросы на подключение,
поступающие на вход процесса-сервера:
nsd = accept(sd,address,addrlen);
где sd - дескриптор гнезда, address - указатель на пользователь-
ский массив, в котором ядро возвращает адрес подключаемого клиен-
та, addrlen - размер пользовательского массива. По завершении вы-
полнения функции ядро записывает в переменную addrlen размер
пространства, фактически занятого массивом. Функция возвращает
новый дескриптор гнезда (nsd), отличный от дескриптора sd. Про-
цесс-сервер может продолжать слежение за состоянием объявленного
гнезда, поддерживая связь с клиентом по отдельному каналу (Рису-
нок 11.19).
С помощью системной функции connect делается запрос на подк-
лючение к существующему гнезду:
connect(sd,address,length);
Семантический смысл параметров функции остается прежним (см.
функцию bind), но address указывает уже на выходное гнездо, обра-
зующее противоположный конец линии связи. Оба гнезда должны ис-
пользовать одни и те же домен и протокол связи, и тогда ядро
удостоверит правильность установки линии связи. Если тип гнезда -
дейтаграмма, сообщаемый функцией connect ядру адрес будет исполь-
зоваться в последующих обращениях к функции send через данное
гнездо; в момент вызова никаких соединений не производится.
Функции send и recv выполняют передачу данных через подклю-
ченное гнездо. Синтаксис вызова функции send:
count = send(sd,msg,length,flags);
где sd - дескриптор гнезда, msg - указатель на посылаемые данные,
length - размер данных, count - количество фактически переданных
байт.
Синтаксис вызова системной функции recv:
count = recv(sd,buf,length,flags);
где buf - массив для приема данных, length - ожидаемый объем дан-
ных, count - количество байт, фактически переданных пользователь-
ской программе. Флаги (flags) могут быть установлены таким обра-
зом, что поступившее сообщение после чтения и анализа его содер-
жимого не будет удалено из очереди, или настроены на получение
данных out-of-band. В дейтаграммных версиях указанных функций,
sendto и recvfrom, в качестве дополнительных параметров указыва-
ются адреса. После выполнения подключения к гнездам потокового
типа процессы могут вместо функций send и recv использовать функ-
ции read и write. Таким образом, согласовав тип протокола, серве-
ры могли бы порождать процессы, работающие только с функциями
read и write, словно имеют дело с обычными файлами.
Функция shutdown закрывает гнездовую связь:
shutdown(sd,mode)
где mode указывает, какой из сторон (посылающей, принимающей или
обеим вместе) отныне запрещено участие в процессе передачи дан-
ных. Функция сообщает используемому протоколу о завершении сеанса
сетевого взаимодействия, оставляя, тем не менее, дескрипторы
гнезд в неприкосновенности. Освобождается дескриптор гнезда толь-
ко в результате выполнения функции close.
Таблица показывает шаги в установление связи socket с TCP, и аналогию каждого шага с телефонной.
|
Task 1 Сервер |
Task 2 Клиент |
TCP |
Аналогия с телефонной связью |
|
socket() |
socket() |
Создать сокет. |
Установить телефон. |
|
bind() |
|
Присвоить адрес сокету |
Получить номер телефона |
|
listen() |
|
Разрешить соединение с сокетом |
Включить телефон. |
|
|
connect() |
Затребовать соединение с другим socket. |
Набрать номер другого телефона. |
|
accept() |
|
Подтвердить соединение между sockets |
Поднять трубку и ответить. |
|
write() |
write() |
Send data to other socket. |
Говорить |
|
read() |
read( ) |
Receive data from other socket. |
Слушать |
|
shutdown()
|
shutdown()
|
|
Повесить трубку |
Системная функция getsockname получает имя гнездовой связи,
установленной ранее с помощью функции bind:
getsockname(sd,name,length);
Функции getsockopt и setsockopt получают и устанавливают зна-
чения различных связанных с гнездом параметров в соответствии с
типом домена и протокола.
Рассмотрим обслуживающую программу, представленную на Рисунке
