Литмир - Электронная Библиотека
Содержание  
A
A

В листинге 8.8 показан вывод программы

tcpdump
.

Листинг 8.8. Вывод программы tcpdump при запуске функции dg_cli

macosx % <b>tcpdump</b>

01 0.0            macosx.51139 &gt; freebsd4 9877:udp 13

02 0.006180 ( 0.0062) freebsd4 &gt; macosx: icmp: freebsd4 udp port 9877 unreachable

В табл. A.5 мы также видим, что возникшую ошибку ICMP ядро сопоставляет ошибке

ECONNREFUSED
, которая соответствует выводу строки сообщения
Connection refused
(В соединении отказано) функцией
err_sys
.

ПРИМЕЧАНИЕ

К сожалению, не все ядра возвращают сообщения ICMP присоединенному сокету UDP, как мы показали в этом разделе. Обычно ядра реализаций, происходящих от Беркли, возвращают эту ошибку, а ядра System V — не возвращают. Например, если мы запустим тот же клиент на узле Solaris 2.4 и с помощью функции connect соединимся с узлом, на котором не запущен наш сервер, то с помощью программы tcpdump мы сможем убедиться, что ошибка ICMP о недоступности порта возвращается узлом сервера, но вызванная клиентом функция read никогда не завершается. Эта ситуация была исправлена в Solaris 2.5. UnixWare не возвращает ошибку, в то время как AIX, Digital Unix, HP-UX и Linux возвращают.

8.13. Отсутствие управления потоком в UDP

Теперь мы проверим, как влияет на работу приложения отсутствие какого-либо управления потоком в UDP. Сначала мы изменим нашу функцию

dg_cli
так, чтобы она отправляла фиксированное число дейтаграмм. Она больше не будет читать из стандартного потока ввода. В листинге 8.9 показана новая версия функции. Эта функция отправляет серверу 2000 дейтаграмм UDP по 1400 байт каждая.

Листинг 8.9. Функция dg_cli, отсылающая фиксированное число дейтаграмм серверу

//udpcliserv/dgcliloop1.c

 1 #include &quot;unp.h&quot;

 2 #define NDG 2000 /* количество дейтаграмм для отправки */

 3 #define DGLEN 1400 /* длина каждой дейтаграммы */

 4 void

 5 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)

 6 {

 7  int i;

 8  char sendline[DGLEN];

 9  for (i = 0; i &lt; NDG; i++) {

10   Sendto(sockfd, sendline, DGLEN, 0, pservaddr, servlen);

11  }

12 }

Затем мы изменяем сервер так, чтобы он получал дейтаграммы и считал число полученных дейтаграмм. Сервер больше не отражает дейтаграммы обратно клиенту. В листинге 8.10 показана новая функция

dg_echo
. Когда мы завершаем процесс сервера нажатием клавиши прерывания на терминале (что приводит к отправке сигнала
SIGINT
процессу), сервер выводит число полученных дейтаграмм и завершается.

Листинг 8.10. Функция dg_echo, считающая полученные дейтаграммы

//udpcliserv/dgecholoop1.c

 1 #include &quot;unp.h&quot;

 2 static void recvfrom_int(int);

 3 static int count;

 4 void

 5 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)

 6 {

 7  socklen_t len;

 8  char mesg[MAXLINE];

 9  Signal (SIGINT, recvfrom_int);

10  for (;;) {

11   len = clilen;

12   Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &amp;len);

13   count++;

14  }

15 }

16 static void

17 recvfrom_int(int signo)

18 {

19  printf(&quot;\nreceived %d datagrams\n&quot;, count);

20  exit(0);

21 }

Теперь мы запускаем сервер на узле

freebsd
, который представляет собой медленный компьютер SPARCStation. Клиент мы запускаем в значительно более быстрой системе RS/6000 с операционной системой
aix
. Они соединены друг с другом напрямую каналом Ethernet на 100 Мбит/с. Кроме того, мы запускаем программу
netstat -s
на узле сервера и до, и после запуска клиента и сервера, поскольку выводимая статистика покажет, сколько дейтаграмм мы потеряли. В листинге 8.11 показан вывод сервера.

Листинг 8.11. Вывод на узле сервера

freebsd % <b>netstat -s -p udp</b>

udp:

 71208 datagrams received

 0 with incomplete header

 0 with bad data length field

 0 with bad checksum

 0 with no checksum

 832 dropped due to no socket

 16 broadcast/multicast datagrams dropped due to no socket

 1971 dropped due to full socket buffers

 0 not for hashed pcb

 68389 delivered

 137685 datagrams output

freebsd % <b>udpserv06</b> <i>запускаем наш сервер</i>

<i>                    клиент посылает дейтаграммы</i>

<b>^C </b><i>для окончания работы клиента вводим наш символ прерывания</i>

freebsd % <b>netstat -s -р udp</b>

udp

 73208 datagrams received

 0 with incomplete header

 0 with bad data length field

103
{"b":"225366","o":1}