Литмир - Электронная Библиотека
Содержание  
A
A

11  cliaddr = Malloc(MAXSOCKADDR);

12  len = MAXSOCKADDR;

13  Getpeername(0, cliaddr, &len);

14  err_msg("connection from %s", Sock_ntop(cliaddr, len));

15  ticks = time(NULL);

16  snprintf(buff, sizeof(buff), "%.24s\r\n\", ctime(&ticks));

17  Write(0, buff, strlen(buff));

18  Close(0); /* закрываем соединение TCP */

19  exit(0);

20 }

В программе сделано два важных изменения. Во-первых, исчез весь код создания сокета: вызовы функций

tcp_listen
и
accept
. Эти шаги выполняются демоном
inetd
, и мы ссылаемся на соединение TCP, используя нулевой дескриптор (стандартный поток ввода). Во-вторых, исчез бесконечный цикл
for
, поскольку сервер активизируется по одному разу для каждого клиентского соединения. После предоставления сервиса клиенту сервер завершает свою работу.

Вызов функции getpeername

11-14
 Поскольку мы не вызываем функцию
tcp_listen
, мы не знаем размера структуры адреса сокета, которую она возвращает, а поскольку мы не вызываем функцию
accept
, то не знаем и адреса протокола клиента. Следовательно, мы выделяем буфер для структуры адреса сокета, используя нашу константу
MAXSOCKADDR
и вызываем функцию
getpeername
с нулевым дескриптором в качестве первого аргумента.

Чтобы выполнить этот пример в нашей системе Solaris, сначала мы присваиваем службе имя и порт, добавляя следующую строку в

/etc/services
:

mydaytime 9999/tcp

Затем добавляем строку в

/etc/inetd.conf
:

mydaytime stream tcp nowait andy

/home/andy/daytimetcpsrv3 daytimetcpsrv3

(Мы разбили длинную строку на более короткие.) Мы помещаем выполняемый код в заданный файл и отправляем демону

inetd
сигнал
SIGHUP
, сообщающий ему, что нужно заново считать файл конфигурации. Следующий шаг — выполнить программу
netstat
, чтобы проверить, что на порте TCP 9999 создан прослушиваемый сокет:

solaris % <b>netstat -na | grep 9999</b>

*.9999 *.* 0 0 49152 0 LISTEN

Затем мы запускаем сервер с другого узла:

linux % <b>telnet solaris 9999</b>

Trying 192.168.1.20...

Connected to solaris.

Escape character is '^]'.

Tue Jun 10 11:04:02 2003

Connection closed by foreign host.

Файл

/var/amd/messages
(в который, как указано в нашем файле
/etc/syslog.conf
, должны направляться наши сообщения с аргументом
facility=LOG_USER
) содержит запись:

Jun 10 11:04:02 solaris daytimetcpsrv3[28724]: connection from 192.168.1.10.58145

13.7. Резюме

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

syslogd
при помощи вызова функции
syslog
. Администратор полностью контролирует все, что происходит с этими сообщениями, основываясь на том, какой демон отправил данное сообщение и насколько оно серьезно.

Чтобы запустить произвольную программу и выполнять ее в качестве демона, требуется пройти несколько шагов: вызвать функцию

fork
для запуска в фоновом режиме, вызвать функцию
setsid
для того, чтобы создать новый сеанс POSIX и стать главным процессом сеанса, снова вызвать функцию
fork
, чтобы избежать перехода в режим управления с терминала, изменить рабочий каталог и маску режима создания файла и закрыть все ненужные файлы. Наша функция
daemon_init
выполняет все эти шаги.

Многие серверы Unix запускаются демоном

inetd
. Он осуществляет все необходимые шаги по превращению процесса в демон, и при запуске действительного сервера открывается сокет для стандартных потоков ввода, вывода и сообщений об ошибках. Это позволяет нам опустить вызовы функций
socket
,
bind
,
listen
и
accept
, поскольку все эти шаги выполняются демоном
inetd
.

Упражнения

1. Что произойдет в листинге 13.2, если мы отложим вызов функции

daemon_init
до завершения обработки аргументов командной строки и функция
err_quit
будет вызвана до того, как программа станет демоном?

2. Как вы думаете, какие из 10 серверов, перечисленных в табл. 2.1 (учитываются версии TCP и UDP для каждой из пяти служб, управляемых демоном

inetd
), реализуются с помощью вызова функции fork, а какие не требуют этой функции?

3. Что произойдет, если мы создадим сокет UDP, свяжем порт 7 с сокетом (стандартный эхо-сервер в табл. 2.1) и отправим дейтаграмму UDP-серверу

chargen
?

4. В руководстве Solaris 2.x для демона

inetd
описывается флаг
-t
, заставляющий демон
inetd
вызывать функцию
syslog
(с аргументами
facility=LOG_DAEMON
и
level=LOG_NOTICE
) для протоколирования клиентского IP-адреса и порта любой службы TCP, которые обрабатывает демон
inetd
. Как демон
inetd
получает эту информацию?

В этом же руководстве сказано, что демон

inetd
не может выполнить это для сокета UDP. Почему?

Есть ли способ обойти эти ограничения для служб UDP?

Глава 14

Дополнительные функции ввода-вывода

14.1. Введение

Эта глава охватывает разнообразные функции и технологии, которые мы помещаем в общую категорию «расширенного ввода-вывода». Сначала мы описываем установку тайм-аута для операции ввода-вывода, которую можно выполнить тремя различными способами. Затем мы рассматриваем три варианта функций

read
и
write
:
recv
и
send
, допускающие четвертый аргумент, содержащий флаги, передаваемые от процесса к ядру;
readv
и
writev
, позволяющие нам задавать массив буферов для ввода или вывода;
recvmsg
и
sendmsg
, объединяющие все свойства других функций ввода-вывода и обладающие новой возможностью получения и отправки вспомогательных данных.

153
{"b":"225366","o":1}