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

на главную

Жанры

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

13-15
Мы вызываем функцию
getpeername
, чтобы получить адрес протокола сервера и вывести его. Мы делаем это для проверки протокола, используемого в примерах, которые скоро покажем.

Обратите внимание, что функция

tcp_connect
не возвращает размера структуры адреса сокета, который использовался для функции
connect
. Мы могли добавить еще один аргумент-указатель, чтобы получить это значение, но при создании этой функции мы стремились добиться меньшего числа аргументов, чем у функции
getaddrinfo
.
Поэтому мы определяем константу
MAXSOCKADDR
в нашем заголовке
unp.h
так, чтобы ее размер равнялся размеру наибольшей структуры адреса сокета. Обычно это размер структуры адреса доменного сокета Unix (см. раздел 14.2), немного более 100 байт. Мы выделяем в памяти пространство для структуры указанного размера и заполняем ее с помощью функции
getpeername
.

Эта версия нашего клиента работает и с IPv4, и с IPv6, тогда как версия, представленная в листинге 1.1, работала только с IPv4, а версия из листинга 1.2 — только с IPv6. Сравните нашу новую версию с представленной в листинге Д.6, которую мы написали, чтобы использовать функции

gethostbyname
и
getservbyname
для поддержки и IPv4, и IPv6.

Сначала мы задаем имя узла, поддерживающего только IPv4:

freebsd % daytimetcpcli linux daytime

connected to 206 168.112.96

Sun Jul 27 23:06:24 2003

Затем мы задаем имя узла, поддерживающего и IPv4, и IPv6:

freebsd % daytimetcpcli aix daytime

connected to 3ffe:b80:1f8d:2:204:acff:fe17:bf38

Sun Jul 27 23:17:13 2003

Используется адрес IPv6, поскольку у узла имеется и запись типа AAAA, и запись типа А. Кроме того, функция

tcp_connect
устанавливает семейство адресов
AF_UNSPEC
, поэтому, как было отмечено в табл. 11.3, сначала идет поиск записей типа AAAA, и только если этот поиск неудачен, выполняется поиск записей типа А.

В следующем примере мы указываем на необходимость использования именно адреса IPv4, задавая имя узла с суффиксом

– 4
, что, как мы отмечали в разделе 11.2, в соответствии с принятым нами соглашением означает имя узла, который поддерживает только записи типа А:

freebsd % daytimetcpcli aix-4 daytime

connected to 192.168.42.2

Sun Jul 27 23:17:48 2003

11.13. Функция tcp_listen

Наша следующая функция,

tcp_listen
, выполняет обычные шаги сервера TCP: создание сокета TCP, связывание его с заранее известным портом с помощью функции bind и разрешение приема входящих запросов через соединение. В листинге 11.6 представлен исходный код.

#include "unp.h"

int tcp_listen(const char * hostname, const char * service, socklen_t * lenptr);

В
случае успешного выполнения возвращает дескриптор присоединенного сокета, в случае ошибки не возвращает ничего

Листинг 11.6. Функция tcp_listen: выполнение обычных шагов сервера TCP

//lib/tcp_listen.c

1 #include "unp.h"

2 int

3 tcp_listen(const char *host, const char *serv, socklen_t *addrlenp)

4 {

5 int listenfd, n;

6 const int on = 1;

7 struct addrinfo hints, *res, *ressave;

8 bzero(&hints, sizeof(struct addrinfo));

9 hints.ai_flags = AI_PASSIVE;

10 hints.ai_family = AF_UNSPEC;

11 hints.ai_socktype = SOCK_STREAM;

12 if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)

13 err_quit("tcp_listen error for %s, %s: %s",

14 host, serv, gai_strerror(n));

15 ressave = res;

16 do {

17 listenfd =

18 socket(res->ai_family, res->ai_socktype, res->ai_protocol);

19 if (listenfd < 0)

20 continue; /* ошибка, пробуем следующий адрес */

21 Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

22 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)

23 break; /* успех */

24 Close(listenfd); /* ошибка при вызове функции bind, закрываем

сокет и пробуем следующий адрес*/

25 } while ((res = res->ai_next) != NULL);

26 if (res == NULL) /* значение errno устанавливается при последнем

вызове функции socket или bind */

27 err_sys("tcp_listen error for %s, %s", host, serv);

28 Listen(listenfd, LISTENQ);

29 if (addrlenp)

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

Не грози Дубровскому! Том VIII

Панарин Антон
8. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том VIII

Para bellum

Ланцов Михаил Алексеевич
4. Фрунзе
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Para bellum

Архонт

Прокофьев Роман Юрьевич
5. Стеллар
Фантастика:
боевая фантастика
рпг
7.80
рейтинг книги
Архонт

Сильнейший ученик. Том 2

Ткачев Андрей Юрьевич
2. Пробуждение крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сильнейший ученик. Том 2

Измена. Ребёнок от бывшего мужа

Стар Дана
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Ребёнок от бывшего мужа

Real-Rpg. Город гоблинов

Жгулёв Пётр Николаевич
1. Real-Rpg
Фантастика:
фэнтези
7.81
рейтинг книги
Real-Rpg. Город гоблинов

Хозяйка Междуречья

Алеева Елена
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Хозяйка Междуречья

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Эйгор. В потёмках

Кронос Александр
1. Эйгор
Фантастика:
боевая фантастика
7.00
рейтинг книги
Эйгор. В потёмках

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

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

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Удобная жена

Волкова Виктория Борисовна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Удобная жена