Чтение онлайн

на главную

Жанры

UNIX: разработка сетевых приложений
Шрифт:

14:28:29.614846 12.106.32.254.444 > 192.168.42.2.8888. udp 6

14:28:29.615255 192.168.42.2 > 12 106.32.254: icmp: 192.168 42.2

udp port 8888 unreachable

8.7. Использование функции

printf
на стороне клиента приведет к возникновению задержки между отправками дейтаграмм, что позволит серверу получать большее количество дейтаграмм. Использование функции
printf
на стороне сервера приведет к тому, что сервер будет терять большее количество дейтаграмм.

8.8. Наибольший размер IPv4-дейтаграммы составляет 65 535

байт и ограничивается 16-разрядным полем полной длины, показанным на рис. А.1. IP-заголовок требует 20 байт, UDP-заголовок — 8 байт, и для пользовательских данных остается не более 65 507 байт. В IPv6 (без поддержки джумбограмм) размер IP-заголовка составляет 40 байт, и под пользовательские данные отводится 65 487 байт.

В листинге Д.3 приведена новая версия

dg_cli
. Если забыть установить размер буфера отправки, Беркли-ядра возвратят из функции
sendto
ошибку
EMSGSIZE
, поскольку размер буфера отправки сокета обычно меньше, чем максимально возможный размер UDP-дейтаграммы (чтобы убедиться в этом, выполните упражнение 7.1).

Листинг Д.3. Запись дейтаграммы UDP/IPv4 максимального размера

//udpcliserv/dgclibig.c

1 #include "unp.h"

2 #undef MAXLINE

3 #define MAXLINE 65507

4 void

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

6 {

7 int size;

8 char sendline[MAXLINE], recvline[MAXLINE + 1];

9 ssize_t n;

10 size = 70000;

11 Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));

12 Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));

13 Sendto(sockfd, sendline, MAXLINE, 0, pservaddr, servlen);

14 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);

15 printf("received %d bytes\n", n);

16 }

Но если установить размеры буферов сокета клиента, как показано в листинге Д.3, и запустить программу, сервер ничего не возвратит. С помощью программы

tcpdump
можно убедиться, что клиентская дейтаграмма отправляется серверу, но если в сервер поместить функцию
printf
, вызов функции
recvfrom
не возвратит дейтаграмму. Проблема заключается в том, что приемный буфер UDP-сокета сервера меньше, чем посланная нами дейтаграмма, поэтому дейтаграмма отбрасывается и не доставляется на сокет. В системах BSD/OS это можно проверить, запустив программу
netstat -s
и проверив счетчик, указывающий количество дейтаграмм, отброшенных из-за переполнения буферов сокета (
dropped due to full socket buffers
), до и после получения нашей длинной дейтаграммы. Решением является модификация сервера путем задания размеров буферов приема и отправки сокета.

В большинстве сетей дейтаграмма длиной 65 535 байт фрагментируется. Как отмечалось в разделе 2.9, IP-уровнем должен поддерживаться размер буфера для сборки фрагментов, равный всего лишь 576 байт. Поэтому некоторые узлы не получат дейтаграмму максимального размера, посылаемую в данном упражнении. Кроме того, во многих Беркли-реализациях, включая 4.4BSD-Lite2, имеется ошибка, связанная со знаковыми типами данных, которая не позволяет UDP принимать дейтаграммы больше, чем 32 767 байт (см. строка 95, с. 770 [128]).

Глава 9

9.1. В некоторых ситуациях функция

sctp_peeloff
может оказаться очень полезной. Примером приложения, которому может понадобиться эта функция, является традиционный сервер дейтаграмм, обрабатывающий небольшие транзакции, которому периодически приходится устанавливать долговременные соединения. Чаще всего сервер передает одно-два коротких сообщения, но время от времени поступает запрос на проверку базы сервера, и тогда ему приходится передавать большие объемы данных. В такой ситуации имеет смысл отделить ассоциацию, по которой передаются проверочные данные, для обработки ее отдельным процессом или потоком.

9.2. На стороне сервера выполняется автоматическое закрытие после закрытия ассоциации клиентом. SCTP не поддерживает состояние неполного закрытия, поэтому когда клиент вызывает

close
, все подготовленные сервером данные сбрасываются и ассоциация закрывается.

9.3. Сокет типа «один-к-одному» требует вызова

connect
, поэтому когда собеседнику отсылается сегмент COOKIE, никаких данных в буфере отправки быть еще не может. Сокет типа «один-ко-многим» допускает отправку данных с одновременной установкой соединения. Поэтому сегмент COOKIE в этом случае может быть совмещен с сегментом DATA.

9.4. Собеседник, с которым устанавливается ассоциация, может прислать данные только в том случае, если у него будет готов сегмент DATA до того, как соединение будет установлено, то есть если на обеих сторонах используются сокеты типа «один-ко-многим» и каждая сторона выполняет операцию send с неявной установкой соединения. Такой процесс установки ассоциации называется коллизией пакетов INIT и подробно описывается в главе 4 [117].

9.5. В некоторых случаях не все связанные адреса могут быть переданы собеседнику. В частности, если приложение связало с сокетом как частные, так и общие IP-адреса, собеседник получит информацию только об общих IP-адресах. Еще одним примером являются локальные в рамках канала адреса IPv6, которые не обязательно сообщаются собеседнику.

Глава 10

10.1 Если функция

sctp_sendmsg
возвращает ошибку, сообщение не будет отправлено, а приложение вызовет функцию
sctp_recvmsg
и заблокируется в ней навсегда, ожидая ответного сообщения, которое никогда не придет.

Чтобы избежать этой неприятности, нужно проверять коды возврата. Если при отправке возникла ошибка, клиент не должен пытаться получить ответ. Ему следует просто сообщить о возникшей ошибке.

Если функция

sctp_recvmsg
вернет ошибку, никаких сообщений получено не будет, но сервер все равно попытается отправить сообщение, что может привести к установлению ассоциации. Для предотвращения этого следует проверять код ошибки и, в зависимости от его значения, сообщать об ошибке и закрывать сокет (при этой операции также может быть возвращена ошибка) или повторно вызывать
sctp_recvmsg
.

Поделиться:
Популярные книги

Идеальный мир для Лекаря 7

Сапфир Олег
7. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 7

Враг из прошлого тысячелетия

Еслер Андрей
4. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Враг из прошлого тысячелетия

Кодекс Охотника. Книга XII

Винокуров Юрий
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XII

Жестокая свадьба

Тоцка Тала
Любовные романы:
современные любовные романы
4.87
рейтинг книги
Жестокая свадьба

Идеальный мир для Социопата 4

Сапфир Олег
4. Социопат
Фантастика:
боевая фантастика
6.82
рейтинг книги
Идеальный мир для Социопата 4

Возмездие

Злобин Михаил
4. О чем молчат могилы
Фантастика:
фэнтези
7.47
рейтинг книги
Возмездие

Попаданка в академии драконов 4

Свадьбина Любовь
4. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.47
рейтинг книги
Попаданка в академии драконов 4

(Не)свободные, или Фиктивная жена драконьего военачальника

Найт Алекс
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
(Не)свободные, или Фиктивная жена драконьего военачальника

Убийца

Бубела Олег Николаевич
3. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Убийца

Книга пяти колец. Том 2

Зайцев Константин
2. Книга пяти колец
Фантастика:
фэнтези
боевая фантастика
5.00
рейтинг книги
Книга пяти колец. Том 2

Вечная Война. Книга VII

Винокуров Юрий
7. Вечная Война
Фантастика:
юмористическая фантастика
космическая фантастика
5.75
рейтинг книги
Вечная Война. Книга VII

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2

Матабар. II

Клеванский Кирилл Сергеевич
2. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар. II

Месть Паладина

Юллем Евгений
5. Псевдоним `Испанец`
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Месть Паладина