Уильям Стивенс - UNIX: разработка сетевых приложений Страница 89
- Категория: Компьютеры и Интернет / Программное обеспечение
- Автор: Уильям Стивенс
- Год выпуска: -
- ISBN: -
- Издательство: -
- Страниц: 263
- Добавлено: 2019-07-03 10:23:38
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту pbn.book@yandex.ru для удаления материала
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Уильям Стивенс - UNIX: разработка сетевых приложений» бесплатно полную версию:Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Уильям Стивенс - UNIX: разработка сетевых приложений читать онлайн бесплатно
Функция gethostbyname отличается от других функций сокетов, описанных нами, тем, что она не задает значение переменной errno, когда происходит ошибка. Вместо этого она присваивает глобальной целочисленной переменной h_errno одну из следующих констант, определяемых в заголовке <netdb.h>:
■ HOST_NOT_FOUND;
■ TRY_AGAIN;
■ NO_RECOVERY;
■ NO_DATA (идентично NO_ADDRESS).
Ошибка NO_DATA означает, что заданное имя действительно, но у него нет записи типа А. Примером может служить имя узла, имеющего только запись типа MX.
Самые современные распознаватели предоставляют функцию hstrerror, которая в качестве единственного аргумента получает значение h_errno и возвращает указатель типа const char* на описание ошибки. Некоторые примеры строк, возвращаемых этой функцией, мы увидим в следующем примере.
Пример
В листинге 11.1[1] показана простая программа, вызывающая функцию gethostbyname для любого числа аргументов командной строки и выводящая всю возвращаемую информацию.
Листинг 11.1. Вызов функции и вывод возвращаемой информации
//names/hostent.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 char *ptr, **pptr;
6 char str[INET_ADDRSTRLEN];
7 struct hostent *hptr;
8 while (--argc > 0) {
9 ptr = *++argv;
10 if ((hptr = gethostbyname(ptr)) == NULL) {
11 err_msg("gethostbyname error for host, %s: %s",
12 ptr, hstrerror(h_errno));
13 continue;
14 }
15 printf("official hostname: %s\n", hptr->h_name);
16 for (pptr = hptr->h_aliases; *pptr != NULL; pptr++)
17 printf("\talias: %s\n", *pptr);
18 switch (hptr->h_addrtype) {
19 case AF_INET:
20 pptr = hptr->h_addr_list;
21 for (; *pptr != NULL; pptr++)
22 printf("\taddress: %s\n",
23 Inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str)));
24 break;
25 default:
26 err_ret("unknown address type");
27 break;
28 }
29 }
30 exit(0);
31 }
8-14 Функция gethostbyname вызывается для каждого аргумента командной строки.
15-17 Выводится каноническое имя узла, за которым идет список альтернативных имен.
18-24 Переменная pptr указывает на массив указателей на индивидуальные адреса. Для каждого адреса мы вызываем функцию inet_ntop и выводим возвращаемую строку.
Сначала мы выполняем программу с именем нашего узла aix, у которого имеется только один адрес IPv4:
freebsd % hostent aix
official hostname: aix.unpbook.com
address: 192.168 42.2
Обратите внимание, что официальное имя узла — это FQDN. Кроме того, хотя у узла имеется адрес IPv6, возвращается только адрес IPv4. Следующим будет веб-сервер с несколькими адресами IPv4:
solaris % hostent cnn.com
official hostname: cnn.com
address: 64.236.16.20
address: 64.236.16.52
address: 64.236 16.84
address: 64.236.16.116
address: 64.236.24.4
address: 64.236.24.12
address: 64.236.24.20
address: 64.236.24.28
Далее идет имя, представленное в разделе 11.2 как имя с записью типа CNAME:
solaris % hostent www
official hostname: linux.unpbook.com
alias: www.unpbook.com
address: 206.168.112.219
Как мы и предполагали, официальное имя узла отличается от нашего аргумента командной строки.
Чтобы увидеть строки ошибок, возвращаемые функцией hstrerror, мы сначала задаем несуществующее имя узла, а затем имя, имеющее только запись типа MX:
solaris % hostent nosuchname.invalid
gethostbyname error for host: nosuchname.invalid: Unknown host
solaris % hostent uunet.uu.net
gethostbyname error for host: uunet.uu.net: No address associated with name
11.4 Функция gethostbyaddr
Функция gethostbyaddr получает в качестве аргумента двоичный IP-адрес и пытается найти имя узла, соответствующее этому адресу. Ее действие обратно действию функции gethostbyname.
#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, size_t len, int family);
Возвращает: непустой указатель в случае успешного выполнения, -1 в случае ошибки
Эта функция возвращает указатель на ту же структуру hostent, которую мы описывали при рассмотрении функции gethostbyname. Обычно в этой структуре нас интересует поле h_name, каноническое имя узла.
Аргумент addr не относится к типу char*, но в действительности это указатель на структуру in_addr, содержащую адрес IPv4. Поле len — это длина структуры: 4 для адресов IPv4. Аргумент family будет иметь значение AF_INET.
В терминах DNS функция gethostbyaddr запрашивает у сервера имен запись типа PTR в домене in-addr.arpa.
11.5. Функции getservbyname и getservbyport
Службы, как и узлы, также часто идентифицируются по именам. Используя в нашем коде имя службы вместо номера порта, при условии, что имена служб сопоставляются номерам портов в некотором файле (обычно /etc/services), мы получаем следующее преимущество. Если этой службе будет назначен другой номер порта, то нам будет достаточно изменить одну строку в файле /etc/services, вместо того чтобы перекомпилировать все приложения. Следующая функция, getservbyname, ищет службу по ее заданному имени.
ПРИМЕЧАНИЕКанонический список номеров портов, назначенных определенным службам, поддерживается IANA и располагается по адресу http://www.iana.org/assignments/port-numbers (см. раздел 2.9). Файл /etc/services чаще всего содержит некоторое подмножество списка IANA.
#include <netdb.h>
struct servent *getservbyname(const char *servname, const char *protoname);
Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки
Функция возвращает указатель на следующую структуру:
struct servent {
char *s_name; /* официальное имя службы */
char **s_aliases; /* список псевдонимов */
int s_port; /* номер порта, записанный в сетевом порядке байтов */
char *s_proto; /* протокол, который нужно использовать */
};
Имя службы servname должно быть указано обязательно. Если задан и протокол (то есть если protoname — непустой указатель), то в структуре должен быть указан совпадающий протокол. Некоторые службы Интернета позволяют использовать и TCP, и UDP (например, DNS и все службы, представленные в табл. 2.1), в то время как другие поддерживают только один протокол (протоколу FTP требуется TCP). Если аргумент protoname не задан и служба поддерживает несколько протоколов, то возвращаемый номер порта зависит от реализации. Обычно это не имеет значения, поскольку службы, поддерживающие множество протоколов, как правило, используют один и тот же номер порта для протоколов TCP и UDP, но вообще говоря это не гарантируется.
Более всего в структуре servent нас интересует поле номера порта. Поскольку номер порта возвращается в сетевом порядке байтов, мы не должны вызывать функцию htons при записи его в структуру адреса сокета.
Типичные вызовы этой функции могут быть такими:
struct servent *sptr;
sptr = getservbyname("domain", "udp"); /* DNS с использованием UDP */
sptr = getservbyname("ftp", "tcp"); /* FTP с использованием TCP */
sptr = getservbyname("ftp", NULL); /* FTP с использованием TCP */
sptr = getservbyname("ftp", "udp"); /* этот вызов приведет к ошибке */
Поскольку протоколом FTP поддерживается только TCP, второй и третий вызовы эквивалентны, а четвертый вызов приводит к ошибке. Вот соответствующие строки из файла /etc/services:
freebsd % grep -e ^ftp -e ^domain /etc/services
ftp-data 20/tcp #File Transfer [Default Data]
ftp 21/tcp #File Transfer [Control]
domain 53/tcp #Domain Name Server
domain 53/udp #Domain Name Server
ftp-agent 574/tcp #FTP Software Agent System
ftp-agent 574/udp #FTP Software Agent System
ftps-data 989/tcp # ftp protocol, data, over TLS/SSL
ftps 990/tcp # ftp protocol, control, over TLS/SSL
Следующая функция, getservbyport, ищет службу по заданному номеру порта и (не обязательно) протоколу.
#include <netdb.h>
struct servent *getservbyport(int port, const char *protname);
Возвращает: непустой указатель в случае успешного выполнения, NULL в случае ошибки
Значение аргумента port должно быть записано в сетевом порядке байтов. Типичные примеры вызова этой функции приведены ниже:
Жалоба
Напишите нам, и мы в срочном порядке примем меры.