Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Листинг 13.4 представляет собой модификацию нашего сервера времени и даты, показанного в листинге 13.2, который может быть активизирован демоном inetd
.
Листинг 13.4. Не зависящий от протокола сервер времени и даты, который может быть активизирован демоном inetd
//inetd/daytimetcpsrv3.c
1 #include "unp.h"
2 #include
3 int
4 main(int argc, char **argv)
5 {
6 socklen_t len;
7 struct sockaddr *cliaddr;
8 char buff[MAXLINE];
9 time_t ticks;
10 daemon_inetd(argv[0], 0);
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
, поскольку сервер активизируется по одному разу для каждого клиентского соединения. После предоставления сервиса клиенту сервер завершает свою работу.
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 % netstat -na | grep 9999
*.9999 *.* 0 0 49152 0 LISTEN
Затем мы запускаем сервер с другого узла:
linux % telnet solaris 9999
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
, объединяющие все свойства других функций ввода-вывода и обладающие новой возможностью получения и отправки вспомогательных данных.
Мы также рассказываем о том, как определить, сколько данных находится в приемном буфере сокета и как использовать с сокетами стандартную библиотеку ввода-вывода С, и обсуждаем более совершенные способы ожидания событий.
14.2. Тайм-ауты сокета
Существует три способа установки тайм-аута для операции ввода-вывода через сокет.
1. Вызов функции alarm
, которая генерирует сигнал SIGALRM
, когда истекает заданное время. Это подразумевает обработку сигналов, которая может варьироваться от одной реализации к другой. К тому же такой подход может стать помехой другим существующим вызовам функции alarm
в данном процессе.
Интервал:
Закладка: