UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
6 * -1 при сообщении ICMP port unreachable (цель достигнута) 7 * неотрицательные значения соответствуют всем прочим ошибкам ICMP 8 */ 9 int10 recv_v4(int seq, struct timeval *tv)11 {12 int hlen1, hlen2, icmplen, ret;13 socklen_t len;14 ssize_t n;15 struct ip *ip, *hip;16 struct icmp *icmp;17 struct udphdr *udp;18 gotalarm = 0;19 alarm(3);20 for (;;) {21 if (gotalarm)22 return(-3); /* истек таймер */23 len = pr->salen;24 n = recvfrom(recvfd, recvbuf, sizeof(recvbuf), 0, pr->sarecv, &len);25 if (n < 0) {26 if (errno == EINTR)27 continue;28 else29 err_sys("recvfrom error");30 }31 ip = (struct ip*)recvbuf; /* начало IP-заголовка */32 hlenl = ip->ip_hl << 2; /* длина IP-заголовка */33 icmp = (struct icmp*)(recvbuf + hlen1); /* начало ICMP-заголовка */34 if ((icmplen = n - hlen1) < 8)35 continue; /* недостаточно данных для проверки ICMP-заголовка */36 if (icmp->icmp_type == ICMP_TIMXCEED &&37 icmp->icmp_code == ICMP_TIMXCEED_INTRANS) {38 if (icmplen < 8 + sizeof(struct ip))39 continue; /* недостаточно данных для проверки внутреннего IP */40 hip = (struct ip*)(recvbuf + hlen1 + 8);41 hlen2 = hip->ip_hl << 2;42 if (icmplen < 8 + hlen2 + 4)43 continue; /* недостаточно данных для проверки UDP-порта */44 udp = (struct udphdr*)(recvbuf + hlen1 + 8 + hlen2);45 if (hip->ip_p == IPPROTO_UDP &&46 udp->uh_sport == htons(sport) &&47 udp->uh_dport == htons(dport + seq)) {48 ret = -2; /* ответил промежуточный маршрутизатор */49 break;50 }51 } else if (icmp->icmp_type == ICMP_UNREACH) {52 if (icmplen < 8 + sizeof(struct ip))53 continue; /* недостаточно данных для проверки внутреннего IP */54 hip = (struct ip*)(recvbuf + hlen1 + 8);55 hlen2 = hip->ip_hl << 2;56 if (icmplen < 8 + hlen2 + 4)57 continue; /* недостаточно данных для проверки UDP-портов */58 udp = (struct udphdr*)(recvbuf + hlen1 + 8 + hlen2);59 if (hip->ip_p == IPPROTO_UDP &&60 udp->uh_sport == htons(sport) &&61 udp->uh_dport == htons(dport + seq)) {62 if (icmp->icmp_code == ICMP_UNREACH_PORT)63 ret = -1; /* цель достигнута */64 else65 ret = icmp->icmp_code; /* 0, 1, 2, ... */66 break;67 }68 }69 if (verbose) {70 printf(" (from %s: type = %d, code - %d)n",71 Sock_ntop_host(pr->sarecv, pr->salen),72 icmp->icmp_type, icmp->icmp_code);73 }74 /* другая ICMP-ошибка, нужно снова вызвать recvfrom() */75 }76 alarm(0); /* отключаем таймер */77 Gettimeofday(tv, NULL); /* время получения пакета */78 return(ret);79 }17-27recvfromЭта функция не создает ситуации гонок, описанной в разделе 20.5, благодаря использованию глобального флага.
31-35iрicmp
Рис. 28.5. Заголовки, указатели и длины при обработке ошибки
