
- •Подсистема управления вводом-выводом
- •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" гнездо потокового
11.20. Процесс создает в домене "unix system" гнездо потокового
типа и присваивает ему имя sockname. Затем с помощью функции
listen устанавливается длина очереди поступающих сообщений и на-
чинается цикл ожидания поступления запросов. Функция accept при-
останавливает свое выполнение до тех пор, пока протоколом не бу-
дет зарегистрирован запрос на подключение к гнезду с означенным
именем; после этого функция завершается, возвращая поступившему
запросу новый дескриптор гнезда. Процесс-сервер порождает потом-
ка, через которого будет поддерживаться связь с процессом-клиен-
том; родитель и потомок при этом закрывают свои дескрипторы, что-
бы они не становились помехой для коммуникационного траффика
другого процесса. Процесс-потомок ведет разговор с клиентом и за-
вершается после выхода из функции read. Процесс-сервер возвраща-
-------------------------------------------------------------¬
¦ #include <sys/types.h> ¦
¦ #include <sys/socket.h> ¦
¦ ¦
¦ main() ¦
¦ { ¦
¦ int sd,ns; ¦
¦ char buf[256]; ¦
¦ struct sockaddr sockaddr; ¦
¦ int fromlen; ¦
¦ ¦
¦ sd = socket(AF_UNIX,SOCK_STREAM,0); ¦
¦ ¦
¦ /* имя гнезда - не может включать пустой символ */ ¦
¦ bind(sd,"sockname",sizeof("sockname") - 1); ¦
¦ listen(sd,1); ¦
¦ ¦
¦ for (;;) ¦
¦ { ¦
¦ ¦
¦ ns = accept(sd,&sockaddr,&fromlen); ¦
¦ if (fork() == 0) ¦
¦ { ¦
¦ /* потомок */ ¦
¦ close(sd); ¦
¦ read(ns,buf,sizeof(buf)); ¦
¦ printf("сервер читает '%s'\n",buf); ¦
¦ exit(); ¦
¦ } ¦
¦ close(ns); ¦
¦ } ¦
¦ } ¦
L-------------------------------------------------------------
Рисунок 11.20. Процесс-сервер в домене "UNIX system"
ется к началу цикла и ждет поступления следующего запроса на
подключение.
На Рисунке 11.21 показан пример процесса-клиента, ведущего
общение с сервером. Клиент создает гнездо в том же домене, что и
сервер, и посылает запрос на подключение к гнезду с именем
sockname. В результате подключения процесс-клиент получает вирту-
альный канал связи с сервером. В рассматриваемом примере клиент
передает одно сообщение и завершается.
Если сервер обслуживает процессы в сети, указание о том, что
гнездо принадлежит домену "Internet", можно сделать следующим об-
разом:
socket(AF_INET,SOCK_STREAM,0);
-------------------------------------------------------------¬
¦ #include <sys/types.h> ¦
¦ #include <sys/socket.h> ¦
¦ ¦
¦ main() ¦
¦ { ¦
¦ int sd,ns; ¦
¦ char buf[256]; ¦
¦ struct sockaddr sockaddr; ¦
¦ int fromlen; ¦
¦ ¦
¦ sd = socket(AF_UNIX,SOCK_STREAM,0); ¦
¦ ¦
¦ /* имя в запросе на подключение не может включать ¦
¦ /* пустой символ */ ¦
¦ if (connect(sd,"sockname",sizeof("sockname") - 1) == -1)¦
¦ exit(); ¦
¦ ¦
¦ write(sd,"hi guy",6); ¦
¦ } ¦
L-------------------------------------------------------------
Рисунок 11.21. Процесс-клиент в домене "UNIX system"
и связаться с сетевым адресом, полученным от сервера. В системе
BSD имеются библиотечные функции, выполняющие эти действия. Вто-
рой параметр вызываемой клиентом функции connect содержит адрес-
ную информацию, необходимую для идентификации машины в сети (или
адреса маршрутов посылки сообщений через промежуточные машины), а
также дополнительную информацию, идентифицирующую приемное гнездо
машины-адресата. Если серверу нужно одновременно следить за сос-
тоянием сети и выполнением локальных процессов, он использует два
гнезда и с помощью функции select определяет, с каким клиентом
устанавливается связь в данный момент.
Порядок следования байтов
В различных компьютерах (в зависимости от типа процессора) целые числа представляются, вообще говоря, по-разному. Имеется два основных способа представления:
первым следует старший байт (big endian);
первым следует младший байт (little endian).
Для определенности при передаче целых чисел по сети используется единый (сетевой) формат. В качестве сетевого используется формат, в котором первым следует старший байт. Для преобразования чисел к сетевому формату и обратно прикладная программа может использовать следующие макросы:
|
htonl() |
преобразование числа типа long к принятому в сети формату; |
|
htons() |
преобразование числа типа short к принятому в сети формату; |
|
ntohl() |
преобразование числа типа long из формата сети в формат данного компьютера; |
|
ntohs() |
преобразование числа типа short из формата сети в формат данного компьютера. |
Макросы HTONL(), HTONS(), NTOHL(), NTOHS() аналогичны макросам htonl(), htons(), ntohl(), ntohs(), но в отличие от них не возвращают никакого значения, а помещают результат на место аргумента.