UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
39 }40 }41 exit(0);42 }Эта программа корректно работает на узле с единственным IP-адресом. Если запустить программу из листинга 11.1 на узле с четырьмя IP-адресами, то получим:
freebsd % <b>hostent cnn.com</b>official hostname: cnn.comaddress: 64.236.16.20address: 64.236.16.52address: 64.236.16.84address: 64.236.16.116address: 64 236.24.4address: 64.236.24.12address: 64.236.24.20address: 64.236.24.28Но если запустить программу из листинга Д.4 на том же узле, в выводе будет только первый IP-адрес:
freebsd % <b>hostent2 cnn.com</b>official hostname: cnn.comaddress: 64.236.24.4name = www1.cnn.comПроблема заключается в том, что две функции,
gethostbynamegethostbyaddrhostentgethostbyaddrh_addr_listgethostbyname11.2. Если ваша система не поддерживает повторно входимую версию функции
gethostbyaddrgethostbyaddrgethostbyname11.3. Сервер
chargen11.4. Эта возможность поддерживается некоторыми распознавателями, но переносимая программа не может использовать ее, потому что POSIX никак ее не оговаривает. В листинге Д.5 приведена измененная версия. Порядок тестирования строки с именем узла имеет значение. Сначала мы вызываем функцию
inet_ptongethostbynameЕсли строка является допустимым IP-адресом в точечно-десятичной записи, мы создаем свой массив указателей (
addrspptrПоскольку адрес уже был переведен в двоичное представление в структуре адреса сокета, мы заменяем вызов функции
memcpymemmoveЛистинг Д.5. Допускаем как использование IP-адреса в точечно-десятичной записи, так и задание имени узла, номера порта или имени службы
//names/daytimetcpcli2.c 1 #include "unp.h" 2 int 3 main(int argc, char **argv) 4 { 5 int sockfd, n; 6 char recvline[MAXLINE + 1]; 7 struct sockaddr_in servaddr; 8 struct in_addr **pptr, *addrs[2]; 9 struct hostent *hp;10 struct servent *sp;11 if (argc != 3)12 err_quit("usage: daytimetcpcli2 <hostname> <service>");13 bzero(&servaddr, sizeof(servaddr));14 servaddr.sin_family = AF_INET;15 if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) == 1) {16 addrs[0] = &servaddr.sin_addr;17 addrs[1] = NULL;18 pptr = &addrs[0];19 } else if ((hp = gethostbyname(argv[1])) != NULL) {20 pptr = (struct in_addr**)hp->h_addr_list;21 } else22 err_quit("hostname error for %s: %s", argv[1], hstrerror(h_errno));23 if ((n = atoi(argv[2])) > 0)24 servaddr.sin_port = htons(n);25 else if ((sp = getservbyname(argv[2], "tcp")) != NULL)26 servaddr.sin_port = sp->s_port;27 else28 err_quit("getservbyname error for %s", argv[2]);29 for (; *pptr != NULL; pptr++) {30 sockfd = Socket(AF_INET, SOCK_STREAM, 0);31 memmove(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));32 printf("trying %sn",33 Sock_ntop((SA*)&servaddr, sizeof(servaddr)));34 if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) == 0)35 break; /* успех */36 err_ret("connect error");37 close(sockfd);38 }39 if (*pptr == NULL)40 err_quit("unable to connect");
