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

ЖАНРЫ

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

socket(AF_INET, SOCK_STREAM, 0)

address: 140.252.3.6.13

socket(AF_INET, SOCK_STREAM, 0)

address: 140.252.4.100.13

socket(AF_INET, SOCK_STREAM, 0)

address: 140.252.1.4.13

Затем мы задаем наш узел

aix
, у которого имеется и запись типа AAAA, и запись типа А, не указывая семейства адресов.
Имя службы —
ftp
, которая предоставляется только TCP.

freebsd % testga -h aix -s ftp -t stream

socket(AF_NET6, SOCK_STREAM, 6)

address: [3ffe:b80:1f8d:2:204:acff:fe17:bf38]:21

socket(AF_INET, SOCK_STREAM, 6)

address: 192.168.42.2:21

Поскольку мы не задали семейство адресов и запустили этот пример на узле, который поддерживает и IPv4, и IPv6, возвращаются две структуры: одна для IPv6 и одна для IPv4.

Затем мы задаем флаг

AI_PASSIVE
(параметр
– р
), не указываем ни семейства адресов, ни имени узла (подразумевая универсальный адрес), задаем номер порта 8888 и не указываем тип сокета.

freebsd % testga -р -s 8888 -t stream

socket(AF_INET6, SOCK_STREAM, 6)

address: [::]:8888

socket(AF_INET, SOCK_STREAM, 6)

address: 0.0.0.0:8888

Возвращаются две структуры. Поскольку мы запустили эту программу на узле, поддерживающем и 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;

Поделиться с друзьями: