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

15.6. Клиент и сервер дейтаграммного доменного протокола Unix

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).

Оглавление книги


Генерация: 1.410. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз