UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
41 while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {42 recvline[n] = 0; /* завершающий нуль */43 Fputs(recvline, stdout);44 }45 exit(0);46 }11.5. Программа приведена в листинге Д.6.
Листинг Д.6. Модификация листинга 11.2 для работы с IPv4 и IPv6
//names/daytimetcpcli3.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 sockaddr_in6 servaddr6; 9 struct sockaddr *sa;10 socklen_t sal en;11 struct in_addr **pptr;12 struct hostent *hp;13 struct servent *sp;14 if (argc != 3)15 err_quit("usage: daytimetcpcli3 <hostname> <service>");16 if ((hp = gethostbyname(argv[1])) == NULL)17 err_quit("hostname error for %s: %s", argv[1], hstrerror(h_errno));18 if ((sp = getservbyname(argv[2], "tcp")) == NULL)19 err_quit("getservbyname error for %s", argv[2]);20 pptr = (struct in_addr**)hp->h_addr_list;21 for (; *pptr != NULL; pptr++) {22 sockfd = Socket(hp->h_addrtype, SOCK_STREAM, 0);23 if (hp->h_addrtype == AF_INET) {24 sa = (SA*)&servaddr;25 salen = sizeof(servaddr);26 } else if (hp->h_addrtype == AF_INET6) {27 sa = (SA*)&servaddr6;28 salen = sizeof(servaddr6);29 } else30 err_quit("unknown addrtype %d", hp->h_addrtype);31 bzero(sa, salen);32 sa->sa_family = hp->h_addrtype;33 sock_set_port(sa, salen, sp->s_port);34 sock_set_addr(sa, salen, *pptr);35 printf("trying %sn", Sock_ntop(sa, salen));36 if (connect(sockfd, sa, salen) == 0)37 break; /* успех */38 err_ret("connect error");39 close(sockfd);40 }41 if (*pptr == NULL)42 err_quit("unable to connect");43 while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {44 recvline[n] = 0; /* завершающий нуль */45 Fputs(recvline, stdout);46 }47 exit(0);48 }Используем значение
h_addrtypegethostbynamesock_set_portsock_set_addrЭта программа работает, однако имеется два ограничения. Во-первых, мы должны обрабатывать все различия, следя за
h_addrtypesasalengetaddrinfo#ifdef11.7. Разместите в памяти большой буфер (превышающий по размеру любую структуру адреса сокета) и вызовите функцию
getsockname11.8. Сначала размещаем в памяти массивы, содержащие имя узла и имя службы:
char host[NI_MAXHOST], serv[NI_MAXSERV];После того как функция
acceptsock_ntopgetnameinfoif (getnameinfo(cliaddr, len, host, NI_MAXHOST, serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) == 0) printf("connection from %s.%sn", host, serv);Поскольку мы имеем дело с сервером, определяем флаги
NI_NUMERICHOSTNI_NUMERICSERV/etc/services11.9. Первая проблема состоит в том, что второй сервер не может связаться (
bindSO_REUSEADDRudp_serverudp_server_reuseaddr
