8.13. Отсутствие управления потоком в UDP
8.13. Отсутствие управления потоком в UDP
Теперь мы проверим, как влияет на работу приложения отсутствие какого-либо управления потоком в UDP. Сначала мы изменим нашу функцию dg_cli так, чтобы она отправляла фиксированное число дейтаграмм. Она больше не будет читать из стандартного потока ввода. В листинге 8.9 показана новая версия функции. Эта функция отправляет серверу 2000 дейтаграмм UDP по 1400 байт каждая.
Листинг 8.9. Функция dg_cli, отсылающая фиксированное число дейтаграмм серверу
//udpcliserv/dgcliloop1.c
1 #include "unp.h"
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 < 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 "unp.h"
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, &len);
13 count++;
14 }
15 }
16 static void
17 recvfrom_int(int signo)
18 {
19 printf(" received %d datagrams ", count);
20 exit(0);
21 }
Теперь мы запускаем сервер на узле freebsd, который представляет собой медленный компьютер SPARCStation. Клиент мы запускаем в значительно более быстрой системе RS/6000 с операционной системой aix. Они соединены друг с другом напрямую каналом Ethernet на 100 Мбит/с. Кроме того, мы запускаем программу netstat -s на узле сервера и до, и после запуска клиента и сервера, поскольку выводимая статистика покажет, сколько дейтаграмм мы потеряли. В листинге 8.11 показан вывод сервера.
Листинг 8.11. Вывод на узле сервера
freebsd % netstat -s -p udp
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 % udpserv06 запускаем наш сервер
клиент посылает дейтаграммы
^C для окончания работы клиента вводим наш символ прерывания
freebsd % netstat -s -р udp
udp
73208 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
3941 dropped due to full socket buffers
0 not for hashed pcb
68419 delivered
137685 datagrams output
Клиент отправил 2000 дейтаграмм, но приложение-сервер получило только 30 из них, что означает уровень потерь 98%. Ни сервер, ни клиент не получают сообщения о том, что эти дейтаграммы потеряны. Как мы и говорили, UDP не имеет возможности управления потоком — он ненадежен. Как мы показали, для отправителя UDP не составляет труда переполнить буфер получателя.
Если мы посмотрим на вывод программы netstat, то увидим, что общее число дейтаграмм, полученных узлом сервера (не приложением-сервером) равно 2000 (73 208 – 71 208). Счетчик dropped due to full socket buffers (отброшено из-за переполнения буферов сокета) показывает, сколько дейтаграмм было получено UDP и проигнорировано из-за того, что приемный буфер принимающего сокета был полон [128, с. 775]. Это значение равно 1970 (3941 – 1971), что при добавлении к выводу счетчика дейтаграмм, полученных приложением (30), дает 2000 дейтаграмм, полученных узлом. К сожалению, счетчик дейтаграмм, отброшенных из-за заполненного буфера, в программе netstat распространяется на всю систему. Не существует способа определить, на какие приложения (например, какие порты UDP) это влияет.
Число дейтаграмм, полученных сервером в этом примере, недетерминировано. Оно зависит от многих факторов, таких как нагрузка сети, загруженность узла клиента и узла сервера.
Если мы запустим тот же клиент и тот же сервер, но на этот раз клиент на медленной системе Sun, а сервер на быстрой системе RS/6000, никакие дейтаграммы не теряются.
aix % udpserv06
^? после окончания работы клиента вводим наш символ прерывания
received 2000 datagrams
Данный текст является ознакомительным фрагментом.