Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
5. Потоковые доменные сокеты Unix аналогичны сокетам TCP: они предоставляют интерфейс байтового потока без границ записей.
6. Если при вызове функции connect для потокового доменного сокета Unix обнаруживается, что очередь прослушиваемого сокета переполнена (см. раздел 4.5), немедленно возвращается ошибка ECONNREFUSED
. В этом отличие от сокета TCP: прослушиваемый сокет TCP игнорирует приходящий сегмент SYN, если очередь сокета заполнена, благодаря чему стеком клиента выполняется несколько попыток отправки сегмента SYN.
7. Дейтаграммные доменные сокеты Unix аналогичны сокетам UDP: они предоставляют ненадежный сервис дейтаграмм, сохраняющий границы записей.
8. В отличие от сокетов UDP, при отправке дейтаграммы на неприсоединенный дейтаграммный доменный сокет Unix с сокетом не связывается полное имя. (Вспомните, что отправка дейтаграммы UDP на неприсоединенный сокет UDP заставляет динамически назначаемый порт связываться с сокетом.) Это означает, что получатель дейтаграммы не будет иметь возможности отправить ответ, если отправитель не связал со своим сокетом полное имя. Аналогично, в отличие от TCP и UDP, при вызове функции connect
для дейтаграммного доменного сокета Unix с сокетом не связывается полное имя.
15.5. Клиент и сервер потокового доменного протокола Unix
Теперь мы перепишем наш эхо-клиент и эхо-сервер TCP из главы 5 с использованием доменных сокетов Unix. В листинге 15.3 показан сервер, который является модификацией сервера из листинга 5.9 и использует потоковый доменный протокол Unix вместо протокола TCP.
Листинг 15.3. Эхо-сервер потокового доменного протокола Unix
//unixdomain/unixstrserv01.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int listenfd, connfd;
6 pid_t childpid;
7 socklen_t clilen;
8 struct sockaddr_un cliaddr, servaddr;
9 void sig_chld(int);
10 listenfd = Socket(AF_LOCAL, SOCK_STREAM, 0);
11 unlink(UNIXSTR_PATH);
12 bzero(&servaddr, sizeof(servaddr));
13 servaddr.sun_family = AF_LOCAL;
14 strcpy(servaddr.sun_path, UNIXSTR_PATH);
15 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
16 Listen(listenfd, LISTENQ);
17 Signal(SIGCHLD, sig_chld);
18 for (;;) {
19 clilen = sizeof(cliaddr);
20 if ((connfd = accept(listenfd, (SA*)&cliaddr, &clilen)) < 0) {
21 if (errno == EINTR)
22 continue; /* назад в for() */
23 else
24 err_sys("accept error");
25 }
26 if ((childpid = Fork()) == 0) { /* дочерний процесс */
27 Close(listenfd); /* закрывается прослушиваемый сокет */
28 str_echo(connfd); /* обработка запроса */
29 exit(0);
30 }
31 Close(connfd); /* родитель закрывает присоединенный сокет */
32 }
33 }
8
Теперь две структуры адреса сокета относятся к типу sockaddr_un
.
10
Для создания потокового доменного сокета Unix первый аргумент функции socket должен иметь значение AF_LOCAL
.
11-15
Константа UNIXSTR_PATH
определяется в файле unp.h
как /tmp/unix/str
. Сначала мы вызываем функцию unlink
, чтобы удалить полное имя в случае, если оно сохранилось после предыдущего запуска сервера, а затем инициализируем структуру адреса сокета перед вызовом функции bind
. Ошибка при выполнении функции unlink
не является аварийной ситуацией.
Обратите внимание, что этот вызов функции bind
отличается от вызова, показанного в листинге 15.2. Здесь мы задаем размер структуры адреса сокета (третий аргумент) как общий размер структуры sockaddr_un
, а не просто число байтов, занимаемое полным именем. Оба значения длины приемлемы, поскольку полное имя должно оканчиваться нулем.
Оставшаяся часть функции такая же, как и в листинге 5.9. Используется та же функция str_echo
(см. листинг 5.2).
В листинге 15.4 представлен эхо-клиент потокового доменного протокола Unix. Это модификация листинга 5.3.
Листинг 15.4. Эхо-клиент потокового доменного протокола Unix
//unixdomain/umxstrcli01.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int sockfd;
6 struct sockaddr_un servaddr;
7 sockfd = Socket(AF_LOCAL, SOCK_STREAM, 0);
8 bzero(&servaddr, sizeof(servaddr));
9 servaddr sun_family = AF_LOCAL;
10 strcpy(servaddr.sun_path, UNIXSTR_PATH);
11 Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));
12 str_cli(stdin, sockfd); /* выполняет всю работу */
13 exit(0);
14 }
6
Теперь структурой адреса сокета, которая должна содержать адрес сервера, будет структура sockaddr_un
.
7
Первый аргумент функции socket
— AF_LOCAL
.
8-10
Код для заполнения структуры адреса сокета идентичен коду, показанному для сервера: инициализация структуры нулем, установка семейства протоколов AF_LOCAL
и копирование полного имени в элемент sun_path
.
12
Функция str_cli
— та же, что и раньше (в листинге 6.2 представлена последняя разработанная нами версия).
15.6. Клиент и сервер дейтаграммного доменного протокола Unix
Теперь мы перепишем наши клиент и сервер UDP из разделов 8.3 и 8.5 с использованием сокетов. В листинге 15.5 показан сервер, который является модификацией листинга 8.1.
Листинг 15.5. Эхо-сервер дейтаграммного доменного протокола Unix
//unixdomain/unixdgserv01.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int sockfd;
6 struct sockaddr_un servaddr, cliaddr;
7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);
8 unlink(UNIXDG_PATH);
9 bzero(&servaddr, sizeof(servaddr));
10 servaddr.sun_family = AF_LOCAL;
11 strcpy(servaddr.sun_path, UNIXDG_PATH);
12 Bind(sockfd, (SA*)&servaddr, sizeof(servaddr));
13 dg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr));
14 }
6
Две структуры адреса сокета относятся теперь к типу sockaddr_un
.
7
Для создания дейтаграммного доменного сокета Unix первый аргумент функции socket
должен иметь значение AF_LOCAL
.
8-12
Константа UNIXDG_PATH
определяется в заголовочном файле unp.h
как /tmp/unix.dg
. Сначала мы вызываем функцию unlink
, чтобы удалить полное имя в случае, если оно сохранилось после предыдущего запуска сервера, а затем инициализируем структуру адреса сокета перед вызовом функции bind
. Ошибка при выполнении функции unlink
— это нормальное явление.
13
Используется та же функция dg_echo
(см. листинг 8.2).
В листинге 15.6 представлен эхо-клиент дейтаграммного доменного протокола Unix. Это модификация листинга 8.3.
Листинг 15.6. Эхо-клиент дейтаграммного доменного протокола Unix
//unixdomain/unixdgcli01.с
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int sockfd;
6 struct sockaddr_un cliaddr, servaddr;
7 sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);
8 bzero(&cliaddr, sizeof(cliaddr)); /* связывание сокета с адресом */
9 cliaddr.sun_family = AF_LOCAL;
10 strcpy(cliaddr.sun_path, tmpnam(NULL);
11 Bind(sockfd, (SA*)&cliaddr, sizeof(cliaddr));
12 bzero(&servaddr, sizeof(servaddr)); /* заполняем структуру адреса
Интервал:
Закладка: