Чтение онлайн

на главную

Жанры

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

18 sa->sin_port = htons(SERV_PORT);

19 Bind(sockfd, (SA*)sa, sizeof(*sa));

20 printf("bound %s\n", Sock_ntop((SA*)sa, sizeof(*sa)));

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

22 mydg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr), (SA*)sa);

23 exit(0); /* не выполняется */

24 }

Вызов
функции get_ifi_info для получения информации об интерфейсе

11-12
Функция
get_ifi_info
получает все адреса IPv4, включая дополнительные (псевдонимы), для всех интерфейсов. Затем программа перебирает все структуры
ifi_info
.

Создание сокета UDP и связывание адреса направленной передачи

13-20
Создается сокет UDP, и с ним связывается адрес направленной передачи. Мы также устанавливаем параметр сокета
SO_REUSEADDR
, поскольку мы связываем один и тот же порт (параметр
SERV_PORT
) для всех IP-адресов.

ПРИМЕЧАНИЕ

Не все реализации требуют, чтобы был установлен этот параметр сокета. Например, Беркли-реализации не требуют этого параметра и позволяют с помощью функции bind связать уже связанный порт, если новый связываемый IP-адрес не является универсальным адресом и отличается от всех IP-адресов, уже связанных с портом. Однако Solaris 2.5 для успешного связывания с одним и тем же портом второго адреса направленной передачи требует установки этого параметра.

Порождение дочернего процесса для данного адреса

21-24
Вызывается функция
fork
, порождающая дочерний процесс. В этом дочернем процессе вызывается функция
mydg_echo
, которая ждет прибытия любой дейтаграммы на сокет и отсылает ее обратно отправителю.

В листинге 22.14 показана следующая часть функции

main
, которая обрабатывает широковещательные адреса.

Листинг 22.14. Вторая часть сервера UDP, который с помощью функции bind связывается со всеми адресами

//advio/udpserv03.c

25 if (ifi->ifi_flags & IFF_BROADCAST) {

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

27 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

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

29 sa = (struct sockaddr_in*)ifi->ifi_brdaddr;

30 sa->sin_family = AF_INET;

31 sa->sin_port = htons(SERV_PORT);

32 if (bind(sockfd, (SA*)sa, sizeof(*sa)) < 0) {

33 if (errno == EADDRINUSE) {

34 printf("EADDRINUSE: %s\n",

35 Sock_ntop((SA*)sa, sizeof(*sa)));

36 Close(sockfd);

37 continue;

38 } else

39 err_sys("bind error for %s",

40 Sock_ntop((SA*)sa, sizeof(*sa)));

41 }

42 printf("bound %s\n", Sock_ntop((SA*)sa, sizeof(*sa)));

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

44 mydg_echo(sockfd, (SA*)&cliaddr, sizeof(cliaddr),

45 (SA*)sa);

46 exit(0); /* не выполняется */

47 }

48 }

49 }

Связывание с широковещательными адресами

25-42
Если интерфейс поддерживает широковещательную передачу, создается сокет UDP и с ним связывается широковещательный адрес. На этот раз мы позволим функции
bind
завершиться с ошибкой
EADDRINUSE
, поскольку если у интерфейса имеется несколько дополнительных адресов (псевдонимов) в одной подсети, то каждый из различных адресов направленной передачи будет иметь один и тот же широковещательный адрес. Подобный пример приведен после листинга 17.3. В этом сценарии мы предполагаем, что успешно выполнится только первая функция
bind
.

Порождение дочернего процесса

43-47
Порождается дочерний процесс, и он вызывает функцию
mydg_echo
.

Заключительная часть функции

main
показана в листинге 22.15. В этом коде при помощи функции
bind
происходит связывание с универсальным адресом для обработки любого адреса получателя, отличного от адресов направленной и широковещательной передачи, которые уже связаны. На этот сокет будут приходить только дейтаграммы, предназначенные для ограниченного широковещательного адреса (255.255.255.255).

Листинг 22.15. Заключительная часть сервера UDP, связывающегося со всеми адресами

//advio/udpserv03.c

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

51 sockfd = Socket(AF_INET, SOCK_DGRAM, 0);

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

53 bzero(&wildaddr, sizeof(wildaddr));

54 wildaddr.sin_family = AF_INET;

Поделиться:
Популярные книги

Назад в СССР: 1986 Книга 5

Гаусс Максим
5. Спасти ЧАЭС
Фантастика:
попаданцы
альтернативная история
5.75
рейтинг книги
Назад в СССР: 1986 Книга 5

Неудержимый. Книга III

Боярский Андрей
3. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга III

Мастер 3

Чащин Валерий
3. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Мастер 3

Конструктор

Семин Никита
1. Переломный век
Фантастика:
попаданцы
альтернативная история
4.50
рейтинг книги
Конструктор

Наследник Четырех

Вяч Павел
5. Игра топа
Фантастика:
героическая фантастика
рпг
6.75
рейтинг книги
Наследник Четырех

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Легат

Прокофьев Роман Юрьевич
6. Стеллар
Фантастика:
боевая фантастика
рпг
6.73
рейтинг книги
Легат

Земная жена на экспорт

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Земная жена на экспорт

Идеальный мир для Лекаря 11

Сапфир Олег
11. Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 11

Столичный доктор. Том II

Вязовский Алексей
2. Столичный доктор
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Столичный доктор. Том II

Столичный доктор. Том III

Вязовский Алексей
3. Столичный доктор
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Столичный доктор. Том III

Пропала, или Как влюбить в себя жену

Юнина Наталья
2. Исцели меня
Любовные романы:
современные любовные романы
6.70
рейтинг книги
Пропала, или Как влюбить в себя жену

Нефилим

Демиров Леонид
4. Мания крафта
Фантастика:
фэнтези
боевая фантастика
рпг
7.64
рейтинг книги
Нефилим

Бывший муж

Рузанова Ольга
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Бывший муж