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%. Ни сервер, ни клиент
Если мы посмотрим на вывод программы netstat
dropped due to full socket buffers
(отброшено из-за переполнения буферов сокета) показывает, сколько дейтаграмм было получено UDP и проигнорировано из-за того, что приемный буфер принимающего сокета был полон [128, с. 775]. Это значение равно 1970 (3941 – 1971), что при добавлении к выводу счетчика дейтаграмм, полученных приложением (30), дает 2000 дейтаграмм, полученных узлом. К сожалению, счетчик дейтаграмм, отброшенных из-за заполненного буфера, в программе netstat
распространяется на всю систему. Не существует способа определить, на какие приложения (например, какие порты UDP) это влияет.Число дейтаграмм, полученных сервером в этом примере, недетерминировано. Оно зависит от многих факторов, таких как нагрузка сети, загруженность узла клиента и узла сервера.
Если мы запустим тот же клиент и тот же сервер, но на этот раз клиент на медленной системе Sun, а сервер на быстрой системе RS/6000, никакие дейтаграммы не теряются.
aix % udpserv06
^?
received 2000 datagrams
Приемный буфер сокета UDP
Число дейтаграмм UDP, установленных в очередь UDP, для данного сокета ограничено размером его приемного буфера. Мы можем изменить его с помощью параметра сокета SO_RCVBUF
dg_echo
из листинга 8.10, которая увеличивает размер приемного буфера сокета до 240 Кбайт. Если мы запустим этот сервер в системе Sun, а клиент — в системе RS/6000, то счетчик полученных дейтаграмм будет иметь значение 103. Поскольку это лишь немногим лучше, чем в предыдущем примере с размером буфера, заданным по умолчанию, ясно, что мы пока не получили решения проблемы.Листинг 8.12
. Функция dg_echo, увеличивающая размер приемного буфера сокета//udpcliserv/dgecholоор2.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 int n;
8 socklen_t len;
9 char mesg[MAXLINE];
10 Signal(SIGINT, recvfrom_int);
11 n = 240 * 1024;
12 Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
13 for (;;) {
14 len = clilen;
15 Recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);
16 count++;
17 }
18 }
19 static void
20 recvfrom_int(int signo)
21 {
22 printf("\nreceived %d datagrams\n", count);
23 exit(0);
24 }