books-read.com
books-read.com » Компьютеры и Интернет » Программное обеспечение » Уильям Стивенс - UNIX: разработка сетевых приложений

Уильям Стивенс - UNIX: разработка сетевых приложений

Наш ресурс дает возможность бесплатно читать книгу онлайн Уильям Стивенс - UNIX: разработка сетевых приложений. Жанр: Программное обеспечение издательство -, год -. Сайт books-read.com дает возможность читать полную версию книги без регистрации и sms. Все книги онлайн, не надо качать fb2, epub, txt.
Добавить книгу Уильям Стивенс - UNIX: разработка сетевых приложений в приложение ЧИТАТЬ КНИГУ ОФЛАЙН в приложении ios/android
Перейти на страницу:

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)); /* заполняем структуру адреса

                                           сокета сервера */

13  servaddr.sun_family = AF_LOCAL;

14  strcpy(servaddr.sun_path, UNIXDG_PATH);


15  dg_cli(stdin, sockfd, (SA*)&servaddr, sizeof(servaddr));


16  exit(0);

17 }

6 Структурой адреса сокета, содержащей адрес сервера, теперь будет структура sockaddr_un. Мы также размещаем в памяти одну из этих структур, чтобы она содержала адрес клиента, о чем мы расскажем далее.

7 Первый аргумент функции socket — это AF_LOCAL.

8-11 В отличие от клиента UDP при использовании дейтаграммного доменного протокола Unix требуется явно связать с помощью функции bind полное имя с нашим сокетом, чтобы сервер имел полное имя, на которое он мог бы отправить свой ответ. Мы вызываем функцию tmpnam, чтобы получить уникальное полное имя, с которым затем при помощи функции bind свяжем наш сокет. Вспомните из раздела 15.4, что при отправке дейтаграммы на неприсоединенный дейтаграммный доменный сокет Unix не происходит неявного связывания полного имени с сокетом. Следовательно, если мы опустим этот шаг, вызов сервером функции recvfrom в функции dg_echo возвращает пустое полное имя, что затем приведет к ошибке, когда сервер вызовет функцию sendto.

12-14 Код для заполнения структуры адреса сокета заранее известным полным именем идентичен коду, представленному ранее для сервера.

15 Функция dg_cli остается той же, что и раньше (см. листинг 8.4).

15.7. Передача дескрипторов

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

1. Дочерний процесс использует все открытые дескрипторы совместно с родительским процессом после вызова функции fork.

2. Все дескрипторы обычно остаются открытыми при вызове функции exec.

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

Современные системы Unix предоставляют способ передавать любой открытый дескриптор от одного процесса любому другому процессу. При этом вовсе не обязательно, чтобы процессы были родственными, как родительский и дочерний. Эта технология требует, чтобы мы сначала создали между двумя процессами доменный сокет Unix и затем использовали функцию sendmsg для отправки специального сообщения через этот доменный сокет. Ядро обрабатывает это сообщение специальным образом, передавая открытый дескриптор от отправителя получателю.

Перейти на страницу:

Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - на сайте онлайн книг books-read.com Вы можете читать полные версии книг автора в одном месте.


UNIX: разработка сетевых приложений отзывы

Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор books-read.com


Прокомментировать
Подтвердите что вы не робот:*