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

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

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

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



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



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



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



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



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

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

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать

14  Bind(sockfd, cli, salen);

15  dg_cli(stdin, sockfd, serv, salen);

16  exit(0);

17 }

К сожалению, все три системы, на которых проводилась проверка — FreeBSD 4.8, MacOS X и Linux 2.4.7, — позволяют использовать функцию bind, а затем посылают UDP-дейтаграммы с IP-адресом многоадресной передачи отправителя.

21.3. Если мы запустим программу ping для группы узлов 224.0.0.1 на нашем узле aix, получим следующий вывод:

solaris % ping 224.0.0.1

PING 224.0.0.1: 56 data bytes

64 bytes from 192.168.42.2: icmp_seq=0 ttl=255 time=0 ms

64 bytes from 192.168.42.1: icmp_seq=0 ttl=64 time=1 ms (DUP!)

^C

----224.0.0.1 PING Statistics----

1 packets transmitted. 1 packets received. +1 duplicates. 0% packet loss

round-trip min/avg/max = 0/0/0 ms

Ответили оба узла в правой сети Ethernet на рис. 1.7.

ПРИМЕЧАНИЕ

Для предотвращения определенных типов атак некоторые системы не отвечают на широковещательные и многоадресные ICMP-запросы. Чтобы получить ответ от freebsd, нам пришлось специально настроить эту систему:

freebsd % sysctl net.inet.icmp.bmcastecho=1

21.5. Величина 1 073 741 824 преобразуется в значение с плавающей точкой и делится на 4 294 967 296, что дает значение 0,250. В результате умножения на 1 000 000 получаем значение 250 000 в микросекундах, а это одна четверть секунды. Наибольшая дробная часть получается при делении 4 294 967 295 на 429 4967 296 и составляет 0,99 999 999 976 716 935 634. Умножая это число на 1 000 000 и отбрасывая дробную часть, получаем 999 999 — наибольшее значение количества микросекунд.

Глава 22

22.1. Вспомните, что функция sock_ntop использует свой собственный статический буфер для хранения результата. Если мы вызовем ее дважды в качестве аргумента в вызове printf, второй вызов приведет к перезаписи результата первого вызова.

22.2. Да, если ответ содержит 0 байт пользовательских данных (например, структура hdr).

22.3. Поскольку функция select не изменяет структуру timeval, которая определяет ее ограничение по времени, нам следует заметить время отправки первого пакета (оно возвращается в миллисекундах функцией rtt_ts). Если функция select сообщает, что сокет готов к чтению, заметьте текущее время, а если функция recvmsg вызывается повторно, вычислите новый тайм-аут для функции select.

22.4. Обычным решением будет создать по одному сокету на каждый адрес интерфейса, как было сделано в разделе 22.6, и отправлять ответ с того же сокета, на который пришел запрос.

22.5. Вызов функции getaddrinfо без аргумента имени узла и без флага AI_PASSIVE заставляет эту функцию считать, что используется локальный адрес 0::1 (для IPv6) или 127.0.0.1 (для IPv4). Напомним, что структура адреса сокета IPv6 возвращается функцией getaddrinfo перед структурой адреса сокета IPv4 при условии, что поддерживается протокол IPv6. Если узел поддерживает оба протокола, вызов функции socket в udp_client закончится успешно при указании семейства протоколов AF_INET6.

В листинге Д.9 приведена не зависящая от протокола версия программы.

Листинг Д.9. Не зависящая от протокола версия программы из раздела 22.6

//advio/udpserv04.c

 1 #include "unpifi.h"

 2 void mydg_echo(int, SA*, socklen_t);

 3 int

 4 main(int argc, char **argv)

 5 {

 6  int sockfd, family, port;

 7  const int on = 1;

 8  pid_t pid;

 9  socklen_t salen;

10  struct sockaddr *sa, *wild;

11  struct ifi_info *ifi, *ifihead;

12  if (argc == 2)

13   sockfd = Udp_client(NULL, argv[1], (void**)&sa, &salen);

14  else if (argc == 3)

15   sockfd = Udp_client(argv[1], argv[2], (void**)&sa, &salen);

16  else

17   err_quit("usage; udpserv04 [ <host> ] <service or port>");

18  family = sa->sa_family;

19  port = sock_get_port(sa, salen);

20  Close(sockfd); /* хотим узнать семейство, порт salen */

21  for (ifihead = ifi = Get_ifi_info(family, 1),

22   ifi ! = NULL; ifi = ifi->ifi_next) {

23   /* связывание с многоадресными адресами */

24   sockfd = Socket(family, SOCK_DGRAM, 0);

25   Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

26   sock_set_port(ifi->ifi_addr, salen, port);

27   Bind(sockfd, ifi->ifi_addr, salen);

28   printf("bound %sn", Sock_ntop(ifi->ifi_addr, salen));

29   if ((pid = Fork()) == 0) { /* дочерний процесс */

30    mydg_echo(sockfd, ifi->ifi_addr, salen);

31    exit(0); /* никогда не выполняется */

32   }

33   if (ifi->ifi_flags & IFF_BROADCAST) {

34    /* попытка связывания с широковещательным адресом */

35    sockfd = Socket(family, SOCK_DGRAM, 0);

36    Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

37    sock_set_port(ifi->ifi_brdaddr, salen, port);

38    if (bind(sockfd, ifi->ifi_brdaddr, salen) < 0) {

39     if (errno == EADDRINUSE) {

40      printf("EADDRINUSE: %sn",

41       Sock_ntop(ifi->ifi_brdaddr, salen));

42      Close(sockfd);

43      continue;

44     } else

45      err_sys("bind error for %s",

46     Sock_ntop(ifi->ifi_brdaddr, salen));

47    }

48    printf ("bound %sn", Sock_ntop(ifi->ifi_brdaddr, salen));

49    if ((pid = Fork()) == 0) { /* дочерний процесс */

50     mydg_echo(sockfd, ifi->ifi_brdaddr, salen);

51     exit(0); /* никогда не выполняется */

52    }

53   }

54  }

55  /* связывание с универсальным адресом */

56  sockfd = Socket(family, SOCK_DGRAM, 0);

57  Setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

58  wild = Malloc(salen);

59  memcpy(wild, sa, salen); /* копирует семейство и порт */

60  sock_set_wild(wild, salen);

61  Bind(sockfd, wild, salen);

62  printf("bound %sn", Sock_ntop(wild, salen));

63  if ((pid = Fork()) == 0) { /* дочерний процесс */

64   mydg_echo(sockfd, wild, salen);

65   exit(0); /* никогда не выполняется */

66  }

67  exit(0);

68 }

69 void

70 mydg_echo(int sockfd, SA *myaddr, socklen_t salen)

71 {

72  int n;

73  char mesg[MAXLINE];

74  socklen_t len;

75  struct sockaddr *cli;

76  cli = Malloc(salen);

77  for (;;) {

78   len = salen;

79   n = Recvfrom(sockfd, mesg, MAXLINE, 0, cli, &len);

80   printf("child %d, datagram from %s",

81    getpid(), Sock_ntop(cli, len));

82   printf(", to %sn", Sock_ntop(myaddr, salen));

83   Sendto(sockfd, mesg, n, 0, cli, len),

84  }

85 }

Глава 24

24.1. Да, разница есть. В первом примере два байта отсылаются с единственным срочным указателем, который указывает на байт, следующий за b. Во втором же примере (вызываются две функции) сначала отсылается символ a с указателем срочности, который указывает на следующий за ним байт, а за этим сегментом следует еще один TCP-сегмент, содержащий символ b с другим указателем срочности, указывающим на следующий за ним байт.

24.2. В листинге Д.10 приведена версия программы с использованием функции poll.

Листинг Д.10. Версия программы из листинга 24.4, использующая функцию poll вместо функции select

//oob/tcprecv03p.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int listenfd, connfd, n, justreadoob = 0;

 6  char buff[100];

 7  struct pollfd pollfd[1];

 8  if (argc == 2)

 9   listenfd = Tcp_listen(NULL, argv[1], NULL);

10  else if (argc == 3)

11   listenfd = Tcp_listen(argv[1], argv[2], NULL);

12  else

13   err_quit("usage: tcprecv03p [ <host> ] <port#>");

14  connfd = Accept(listenfd, NULL, NULL);

15  pollfd[0].fd = connfd;

16  pollfd[0].events = POLLRDNORM;

17  for (;;) {

18   if (justreadoob == 0)

19    pollfd[0].events |= POLLRDBAND;

20   Poll(pollfd, 1, INFTIM);

21   if (pollfd[0].revents & POLLRDBAND) {

22    n = Recv(connfd, buff, sizeof(buff) - 1, MSG_OOB);

23    buff[n] = 0; /* завершающий нуль */

24    printf("read %d OOB byte: %sn", n, buff);

25    justreadoob = 1;

26    pollfd[0].events &= ~POLLRDBAND; /* отключение бита */

27   }

28   if (pollfd[0].revents & POLLRDNORM) {

29    if ((n = Read(connfd, buff, sizeof(buff) - 1)) == 0) {

30     printf("received EOFn");

31     exit(0);

32    }

33    buff[n] = 0; /* завершающий нуль */

34    printf("read %d bytes %sn", n, buff);

35    justreadoob = 0;

36   }

37  }

38 }

Глава 25

25.1. Нет, такая модификация приведет к ошибке. Проблема состоит в том, что nqueue уменьшается до того, как завершается обработка элемента массива dg[iget], что позволяет обработчику сигналов считывать новую дейтаграмму в данный элемент массива.

На этой странице вы можете бесплатно читать книгу UNIX: разработка сетевых приложений - Уильям Стивенс бесплатно.
Похожие на UNIX: разработка сетевых приложений - Уильям Стивенс книги

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

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