Шрифт:
Возвращаются две структуры. Поскольку мы запустили эту программу на узле, поддерживающем и IPv4, и IPv6, не задав семейства адресов, функция
getaddrinfo
возвращает универсальный адрес IPv6 и универсальный адрес IPv4. Структура IPv6 возвращается перед структурой IPv4, поскольку, как мы увидим в главе 12, клиент или сервер IPv6 на узле с двойным стеком может взаимодействовать с собеседниками по IPv6 и по IPv4. 11.11. Функция host_serv
Наш первый интерфейс функции
getaddrinfo
не требует от вызывающего процесса размещать в памяти структуру рекомендаций и заполнять ее. Вместо этого аргументами нашей функции host_serv
будут интересующие нас поля — семейство адресов и тип сокета.
#include "unp.h"
struct addrinfo *host_serv(const char * hostname, const char * service, int family, int socktype);
Возвращает: в случае успешного выполнения указатель на структуру addrinfo. NULL в случае ошибки
В листинге 11.3 показан исходный код этой функции.
Листинг 11.3. Функция host_serv
//lib/host_serv.c
1 #include "unp.h"
2 struct addrinfo*
3 host_serv(const char *host, const char *serv, int family, int socktype)
4 {
5 int n;
6 struct addrinfo hints, *res;
7 bzero(&hints, sizeof(struct addrinfo));
8 hints.ai_flags = AI_CANONNAME; /* всегда возвращает каноническое имя */
9 hints.ai_family = family; /* AF_UNSPEC, AF_INET, AF_INET6, ... */
10 hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, ... */
11 if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
12 return (NULL);
13 return (res); /* возвращает указатель на первый элемент в связном
списке */
14 }
7-13
Функция инициализирует структуру рекомендаций ( hints
), вызывает функцию getaddrinfo
и возвращает пустой указатель, если происходит ошибка. Мы вызываем эту функцию в листинге 16.11, когда нам нужно использовать
getaddrinfo
для получения информации об узле и о службе и при этом мы хотим установить соединение самостоятельно. 11.12. Функция tcp_connect
Теперь мы напишем две функции, использующие функцию
getaddrinfo
для обработки большинства сценариев клиентов и серверов TCP, которые мы создаем. Первая из этих функций, tcp_connect
, выполняет обычные шаги клиента: создание сокета TCP и соединение с сервером.
#include "unp.h"
int tcp_connect(const char * hostname, const char * service);
Возвращает: в случае успешного соединения - дескриптор присоединенного сокета, в случае ошибки не возвращается ничего
В листинге 11.4 показан исходный код.
Листинг 11.4. Функция tcp_connect: выполнение обычных шагов клиента
/
/lib/tcp_connect.c
1 #include "unp.h"
2 int
3 tcp_connect(const char *host, const char *serv)
4 {
5 int sockfd, n;
6 struct addrinfo hints, *res, *ressave;
7 bzero(&hints, sizeof(struct addrinfo));
8 hints.ai_family = AF_UNSPEC;
9 hints.ai_socktype = SOCK_STREAM;