Единственное изменение по сравнению с листингом 11.6 — это обработка аргументов командной строки, позволяющая пользователю в дополнение к имени службы или порту задавать либо имя узла, либо IP-адрес для связывания с сервером.
Сначала мы запускаем этот сервер с сокетом IPv4 и затем соединяемся с сервером от клиентов на двух различных узлах, расположенных в локальной подсети:
freebsd % daytimetcpsrv2 0.0.0.0 9999
connection from 192.168.42.2:32961
connection from 192.168.42.2:1389
А теперь мы запустим сервер с сокетом IPv6:
solaris % daytimetcpsrv2 0::0 9999
connection from [3ffe:b80:1f8d:2:204:acff:fe17:bf38]:32964
connection from [3ffe:b80:1f8d:2:230:65ff:fe15:caa7]:49601
connection from [::ffff:192:168:42:3]:32967
connection from [::ffff:192:168:42:3]:49602
Первое
соединение — от узла
aix
, использующего IPv6, а второе — от узла
macosx
, использующего IPv6. Два следующих соединения — от узлов
aix
и
macosx
, но они используют IPv4, а не IPv6. Мы можем определить это, потому что оба адреса клиента, возвращаемые функцией
accept
, являются адресами IPv4, преобразованными к виду IPv6.
Мы только что показали, что сервер IPv6, работающий на узле с двойным стеком, может обрабатывать как клиенты IPv4, так и клиенты IPv6. Адреса IPv4-клиента передаются серверу IPv6 как адреса IPv4, преобразованные к виду IPv6, что мы рассматривали в разделе 12.2.
11.14. Функция udp_client
Наши функции, предоставляющие более простой интерфейс для функции
getaddrinfo
, в случае UDP изменяются: в этом разделе мы представляем клиентскую функцию, создающую неприсоединенный сокет UDP, а в следующем — другую функцию, создающую присоединенный сокет UDP.
#include "unp.h"
int udp_client(const char * hostname, const char * service,
void ** saptr, socklen_t * lenp);
Возвращает: дескриптор неприсоединенного сокета в случае успешного выполнения, в случае ошибки не возвращает ничего
Эта функция создает неприсоединенный сокет UDP, возвращая три элемента. Во-первых, возвращаемое значение функции — это дескриптор сокета. Во-вторых,
saptr
— это адрес указателя (объявляемого вызывающим процессом) на структуру адреса сокета (которая динамически размещается в памяти функцией
udp_client
), и в этой структуре функция хранит IP-адрес получателя и номер порта для будущих вызовов функции
sendto
. Размер этой структуры адреса сокета возвращается как значение переменной, на которую указывает
lenp
. Последний аргумент не может быть пустым указателем (как это допустимо для последнего аргумента функции
tcp_listen
), поскольку длина структуры адреса сокета требуется в любых вызовах функций
sendto
и
recvfrom
.
В листинге 11.9 показан исходный код для этой функции.
Листинг 11.9. Функция udp_client: создание неприсоединенного сокета UDP