UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
25 Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);
26 tv.tv_sec = 5;
27 tv.tv_usec = 0;
28 FD_SET(sockfd, &rset);
29 FD_SET(icmpfd, &rset);
30 if ((n = Select(maxfdp1, &rset, NULL, NULL, &tv)) == 0) {
31 fprintf(stderr, "socket timeoutn");
32 continue;
33 }
34 if (FD_ISSET(sockfd, &rset)) {
35 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
36 recvline[n] = 0; /* завершающий нуль */
37 Fputs(recvline, stdout);
38 }
39 if (FD_ISSET(icmpfd, &rset)) {
40 if ((n = Read(icmpfd, &icmpd_err, sizeof(icmpd_err))) == 0)
41 err_quit("ICMP daemon terminated");
42 else if (n != sizeof(icmpd_err))
43 err_quit("n = %d, expected %d", n, sizeof(icmpd_err)),
44 printf("ICMP error: dest = %s, %s, type = %d, code = %dn",
45 Sock_ntop(&icmpd_err.icmpd_dest, icmpd_err.icmpd_len);
46 strerror(icmpd_err.icmpd_errno),
47 icmpd_err.icmpd_type, icmpd_err.icmpd_code);
48 }
49 }
50 }
26-33
select
select
34-38
39-48
icmpd
icmpd_err
Функция strerror является примером простой, почти тривиальной функции, которая должна быть более переносимой, чем она есть. В ANSI С ничего не говорится об ошибках, возвращаемых этой функцией. В руководстве по операционной системе Solaris 2.5 говорится, что функция возвращает пустой указатель, если ее аргумент выходит за пределы допустимых значений. Это означает, что код наподобие следующего:
printf("%s", strerror(arg));
является некорректным, поскольку strerror может вернуть пустой указатель. Однако реализации FreeBSD, так же как и все реализации исходного кода, которые автор смог найти, обрабатывают неправильный аргумент, возвращая указатель на строку типа «Неизвестная ошибка». Это имеет смысл и означает, что приведенный выше код правильный. POSIX изменил ситуацию, утверждая, что поскольку не предусмотрено значение, сигнализирующее об ошибке, связанной с выходом аргумента за допустимые пределы, функция присваивает переменной errno значение EIVAL. (Ничего не сказано об указателе, возвращаемом в случае ошибки.) Это означает, что полностью правильный код должен обнулить errno, вызвать функцию strerror, проверить, не равняется ли значение errno величине EINVAL, и в случае ошибки вывести некоторое сообщение.
Примеры эхо-клиента UDP
Приведем несколько примеров работы данного клиента, прежде чем рассматривать исходный код демона. Сначала посылаем дейтаграмму на IP-адрес, не связанный с Интернетом:
freebsd % <b>udpcli01 192.0.2.5 echo</b>
<b>hi there</b>
socket timeout
<b>and hello</b>
socket timeout
Мы считаем, что демон
icmpd
В следующем примере дейтаграмма отправляется на порт стандартного эхо- сервера узла, на котором этот сервер не запущен. Мы получаем ожидаемое ICMPv4-сообщение о недоступности порта.
freebsd % <b>udpcli01 aix-4 echo</b>
<b>hello</b>
ICMP error: dest = 192.168.42.2:7. Connection refused, type = 3, code = 1
Выполнив ту же попытку с протоколом IPv6, мы получаем ICMPv6-сообщение о недоступности порта.
freebsd % <b>udpcli01 aix-6 echo hello, world</b>
ICMP error: dest = [3ffe:b80:1f8d:2:204:acff:fe17:bf38]:7. Connection refused, type = 1. code = 4
Демон icmpd
Начинаем описание нашего демона
icmpd
icmpd.h
Листинг 28.23. Заголовочный файл icmpd.h для демона icmpd
//icmpd/icmpd.h
1 #include "unpicmpd.h"
2 struct client {
3 int connfd; /* потоковый доменный сокет Unix к клиенту */
4 int family; /* AF_INET или AF_INET6 */
5 int lport; /* локальный порт, связанный с UDP-сокетом клиента */
6 /* сетевой порядок байтов */
7 } client[FD_SETSIZE];
8 /* глобальные переменные */
9 int fd4, fd6, listenfd, maxi, maxfd, nready;
10 fd_set rset, allset;