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

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

Уважаемые читатели!
Тут можно читать бесплатно UNIX: разработка сетевых приложений - Уильям Стивенс. Жанр: Программное обеспечение. Так же Вы можете читать полную версию (весь текст) онлайн книги без регистрации и SMS на сайте Knigi-online.info (книги онлайн) или прочесть краткое содержание, описание, предисловие (аннотацию) от автора и ознакомиться с отзывами (комментариями) о произведении.
Описание онлайн-книги UNIX: разработка сетевых приложений - Уильям Стивенс:
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

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



📚 "UNIX: разработка сетевых приложений" - это увлекательное путешествие в мир UNIX и сетевого программирования. В книге автор подробно рассматривает основные принципы разработки сетевых приложений под UNIX, раскрывая множество интересных тем и примеров.



Главный герой книги - опытный разработчик, который стремится углубить свои знания в области сетевого программирования под UNIX. Он исследует различные аспекты работы с сетью, изучает протоколы передачи данных и на практике применяет полученные знания.



👨‍💻 Уильям Стивенс - известный специалист в области компьютерных наук, автор множества книг по сетевому программированию. Его работы пользуются популярностью среди разработчиков и студентов по всему миру.



На сайте knigi-online.info вы можете бесплатно и без регистрации слушать аудиокниги онлайн на русском языке. Здесь собраны бестселлеры и лучшие произведения различных жанров, чтобы каждый мог найти что-то по душе.



🎧 Погрузитесь в увлекательный мир UNIX и сетевого программирования вместе с аудиокнигой "UNIX: разработка сетевых приложений" от Уильяма Стивенса. Развивайте свои навыки, открывайте новые горизонты и наслаждайтесь процессом обучения!

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 118 119 120 121 122 123 124 125 126 ... 263

В листинге 15.11 показана последняя функция, write_fd, вызывающая функцию sendmsg для отправки дескриптора (и, возможно, еще каких-либо данных, которые мы не используем) через доменный сокет Unix.

Листинг 15.11. Функция write_fd: передача дескриптора при помощи вызова функции sendmsg

//lib/write_fd.c

 1 #include "unp.h"

 2 ssize_t

 3 write_fd(int fd, void *ptr, size_t nbytes, int sendfd)

 4 {

 5  struct msghdr msg;

 6  struct iovec iov[1];

 7 #ifdef HAVE_MSGHDR_MSG_CONTROL

 8  union {

 9   struct cmsghdr cm;

10   char control[CMSG_SPACE(sizeof(int))];

11  } control_un;

12  struct cmsghdr *cmptr;

13  msg.msg_control = control_un.control;

14  msg.msg_controllen = sizeof(control_un.control);

15  cmptr = CMSG_FIRSTHDR(&msg);

16  cmptr->cmsg_len = CMSG_LEN(sizeof(int));

17  cmptr->cmsg_level = SOL_SOCKET;

18  cmptr->cmsg_type = SCM_RIGHTS;

19  *((int*)CMSG_DATA(cmptr)) = sendfd;

20 #else

21  msg.msg_accrights = (caddr_t)&sendfd;

22  msg.msg_accrightslen = sizeof(int);

23 #endif

24  msg.msg_name = NULL;

25  msg.msg_namelen = 0;

26  iov[0].iov_base = ptr;

27  iov[0].iov_len = nbytes;

28  msg.msg_iov = iov;

29  msg.msg_iovlen = 1;

30  return (sendmsg(fd, &msg, 0));

31 }

Как и в случае функции read_fg, эта функция обрабатывает либо вспомогательные данные, либо права доступа, которые предшествовали вспомогательным данным в более ранних реализациях. В любом случае инициализируется структура msghdr и затем вызывается функция sendmsg.

В разделе 28.7 мы приводим пример передачи дескриптора, в котором участвуют неродственные (unrelated) процессы, а в разделе 30.9 — пример, где задействованы родственные процессы. В них мы будем использовать функции read_fd и write_fd, которые только что описали.

15.8. Получение информации об отправителе

На рис. 14.4 мы показали другой тип информации, передаваемой через доменный сокет Unix в виде вспомогательных данных: информацию об отправителе, которая передается с помощью структуры cmsgcred, определяемой путем включения заголовочного файла <sys/socket.h>. Упаковка и формат данных зависят от операционной системы. Такая возможность появилась только в BSD/OS 2.1. Мы описываем FreeBSD, а прочие варианты Unix во многом подобны ей (проблема обычно состоит в выборе структуры, которую следует использовать для передачи данных). Рассказ об этой возможности мы считаем необходимым, поскольку это важное, хотя и простое дополнение доменных протоколов Unix. Когда клиент и сервер связываются с помощью этих протоколов, серверу часто бывает необходим способ точно узнать, кто является клиентом, чтобы убедиться, что клиент имеет право запрашивать определенный сервис.

struct fcred {

 uid_t fc_ruid;            /* действующий идентификатор пользователя */

 gid_t fc_rgid;            /* действующий групповой идентификатор */

 char  fc_login[MAXLOGNAME]; /* имя setlogin() */

 uid_t fc_uid;             /* идентификатор пользователя */

 short fc_ngroups;         /* количество групп */

 gid_t fc_groups[NGROUPS]; /* дополнительные групповые идентификаторы */

};

#define fc_gid fc_groups[0] /* групповой идентификатор */

Обычно MAXLONGNAME и NGROUPS имеют значение 16. Значение fc_ngroups равно как минимум 1, а первым элементом массива является идентификатор группы.

Эта информация всегда доступна через доменный сокет Unix, хотя отправителю часто приходится принимать дополнительные меры для обеспечения ее отправки вместе с данными, и получателю также приходится выполнять некоторые действия (например, устанавливать параметры сокета). В системе FreeBSD получатель может обойтись вызовом recvmsg с достаточно большим буфером для вспомогательных данных, чтобы туда поместились идентифицирующие данные (листинг 15.12). Однако отправитель обязан включить структуру cmsgcred при отправке данных посредством sendmsg. Хотя включение структуры осуществляется отправителем, заполняется она ядром. Благодаря этому передача идентифицирующих данных через доменный сокет Unix является надежным способом проверки клиента.

Пример

В качестве примера передачи идентифицирующих данных мы изменим наш потоковый доменный сервер Unix, так чтобы он запрашивал идентифицирующие данные клиента. В листинге 15.12 показана новая функция, read_cred, аналогичная функции read, но возвращающая также структуру fcred, содержащую идентифицирующие данные отправителя.

Листинг 15.12. Функция read_cred: чтение и возвращение идентифицирующих данных отправителя

//unixdomain/readcred.c

 1 #include "unp.h"

 2 #define CONTROL_LEN (sizeof(struct cmsghdr) + sizeof(struct cmsgcred))

 3 ssize_t

 4 read_cred(int fd, void *ptr, size_t nbytes, struct cmsgcred *cmsgcredptr)

 5 {

 6  struct msghdr msg;

 7  struct iovec iov[1];

 8  char control[CONTROL_LEN];

 9  int n;

10  msg.msg_name = NULL;

11  msg.msg_namelen = 0;

12  iov[0].iov_base = ptr;

13  iov[0].iov_len = nbytes;

14  msg.msg_iov = iov;

15  msg.msg_iovlen = 1;

16  msg.msg_control = control;

17  msg.msg_controllen = sizeof(control);

18  msg.msg_flags = 0;

19  if ((n = recvmsg(fd, &msg, 0)) < 0)

20   return(n);

21  cmsgcredptr->cmcred_ngroups = 0; /* идентифицирующие данные не получены */

22  if (cmsgcredptr && msg.msg_controllen > 0) {

23   struct cmsghdr *cmptr = (struct cmsghdr*)control;

24   if (cmptr->cmsg_len < CONTROL_LEN)

25    err_quit("control length = %d", cmptr->cmsg_len);

26   if (cmptr->cmsg_level != SOL_SOCKET)

27    err_quit("control level != SOL_SOCKET");

28   if (cmptr->cmsg_type != SCM_CREDS)

29    err_quit("control type != SCM_CREDS");

30   memcpy(cmsgcredptr, CMSG_DATA(cmptr), sizeof(struct cmsgcred));

31  }

32  return(n);

33 }

3-4 Первые три аргумента идентичны аргументам функции read, а четвертый аргумент — это указатель на структуру cmsgcred, которая будет заполнена.

22-31 Если данные были переданы, проверяются длина, уровень и тип вспомогательных данных, и результирующая структура копируется обратно вызывающему процессу. Если никаких идентифицирующих данных не было передано, мы обнуляем структуру. Поскольку число групп (cmcred_ngroups) всегда равно 1 или больше, нулевое значение указывает вызывающему процессу, что ядро не возвратило никаких идентифицирующих данных.

Функция main для нашего эхо-сервера (см. листинг 15.3) остается неизменной. В листинге 15.13 показана новая версия функции str_echo, полученная путем модификации листинга 5.2. Эта функция вызывается дочерним процессом после того, как родительский процесс принял новое клиентское соединение и вызвал функцию fork.

Листинг 15.13. Функция str_echo, запрашивающая идентифицирующие данные клиента

//unixdomain/strecho.c

 1 #include "unp.h"

 2 ssize_t read_cred(int, void*, size_t, struct cmsgcred*);

 3 void

 4 str_echo(int sockfd)

 5 {

 6  ssize_t n;

 7  int i;

 8  char buf[MAXLINE];

 9  struct cmsgcred cred;

10 again:

11  while ((n = read_cred(sockfd, buf, MAXLINE, &cred)) > 0) {

12   if (cred.cmcred_ngroups == 0) {

13    printf("(no credentials returned)n");

14   } else {

15    printf("PID of sender = %dn", cred.cmcred_pid);

16    printf("real user ID = %dn", cred.cmcred_uid);

17    printf("real group ID = %dn", cred.cmcred_gid);

18    printf("effective user ID = %dn", cred.cmcred_euid);

19    printf("%d groups:", cred.cmcred_ngroups - 1);

20    for (i = 1; i < cred.cmcred_ngroups; i++)

21     printf(" %d", cred.cmcred_groups[i]);

22    printf("n");

23   }

24   Writen(sockfd, buf, n);

25  }

26  if (n < 0 && errno == EINTR)

27   goto again;

28  else if (n < 0)

29   err_sys("str_echo: read error");

30 }

11-23 Если идентифицирующие данные возвращаются, они выводятся.

24-25 Оставшаяся часть цикла не меняется. Этот код считывает строки от клиента и затем отправляет их обратно клиенту.

Наш клиент, представленный в листинге 15.4, остается практически неизменным. Мы добавляем передачу пустой структуры cmsgcred при вызове sendmsg, которая заполняется ядром.

Перед запуском клиента определим свои личные данные командой id:

freebsd % id

uid=1007(andy) gid=1007(andy) groups=1007(andy), 0(wheel)

Если мы запустим сервер в одном окне, а клиент в другом, то для сервера после однократного выполнения клиента получим представленный ниже вывод.

1 ... 118 119 120 121 122 123 124 125 126 ... 263
На этой странице вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс бесплатно.
Похожие на UNIX: разработка сетевых приложений - Уильям Стивенс книги

Оставить комментарий

Рейтинговые книги