-->

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

На нашем литературном портале можно бесплатно читать книгу UNIX: разработка сетевых приложений, Стивенс Уильям Ричард-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
UNIX: разработка сетевых приложений
Название: UNIX: разработка сетевых приложений
Дата добавления: 16 январь 2020
Количество просмотров: 374
Читать онлайн

UNIX: разработка сетевых приложений читать книгу онлайн

UNIX: разработка сетевых приложений - читать бесплатно онлайн , автор Стивенс Уильям Ричард

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

Перейти на страницу:

Листинг Д.2. Вывод размера приемного буфера сокета и MSS до и после установления соединения

//sockopt/rcvbuf.c

 1 #include "urp.h"

 2 #include <netinet/tcp.h> /* для TCP_MAXSEG */

 3 int

 4 main(int argc, char **argv)

 5 {

 6  int sockfd, rcvbuf, mss;

 7  socklen_t len;

 8  struct sockaddr_in servaddr;

 9  if (argc != 2)

10   err_quit("usage: rcvbuf <Ipaddress>");

11  sockfd = Socket(AF_INET, SOCK_STREAM, 0);

12  len = sizeof(rcvbuf);

13  Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);

14  len = sizeof(mss);

15  Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len);

16  printf("defaults: SO_RCVBUF = %d. MSS = %dn", rcvbuf, mss);

17  bzero(&servaddr, sizeof(servaddr));

18  servaddr.sin_family = AF_INET;

19  servaddr.sin_port = htons(13); /* сервер времени и даты */

20  Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

21  Connect(sockfd, (SA*)&servaddr, sizeof(servaddr));

22  len = sizeof(rcvbuf);

23  Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len);

24  len = sizeof(mss);

25  Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len);

26  printf("after connect: SO_RCVBUF = %d, MSS = %dn", rcvbuf, mss);

27  exit(0);

28 }

He существует какого-то одного «правильного» вывода для данной программы. Результаты зависят от системы. Некоторые системы (в особенности Solaris 2.5.1 и более ранние версии) всегда возвращают нулевой размер буфера сокета, не давая нам возможности увидеть, что происходит с этим значением в процессе соединения.

До вызова функции

connect
выводится значение MSS по умолчанию (часто 536 или 512), а значение, выводимое после вызова функции connect, зависит от возможных параметров MSS, полученных от собеседника. Например, в локальной сети Ethernet после выполнения функции connect MSS может иметь значение 1460. Однако после соединения (
connect
) с сервером в удаленной сети значение MSS может быть равно значению по умолчанию, если только ваша система не поддерживает обнаружение транспортной MTU. Если это возможно, запустите во время работы вашей программы программу
tcpdump
или подобную ей (см. раздел В.5), чтобы увидеть фактическое значение параметра MSS в сегменте SYN, полученном от собеседника.

Многие реализации после установления соединения округляют размер приемного буфера сокета в большую сторону, чтобы он было кратным MSS. Чтобы узнать размер приемного буфера сокета после установления соединения, можно исследовать пакеты с помощью программы типа

tcpdump
и посмотреть, каков размер объявленного окна TCP.

7.3. Разместите в памяти структуру

linger
по имени
ling
и проинициализируйте ее следующим образом:

str_cli(stdin, sockfd);

ling.l_onoff = 1;

ling.l_linger = 0;

Setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));

exit(0);

Это заставит TCP на стороне клиента прекратить работу путем отправки сегмента RST вместо нормального обмена четырьмя сегментами. Дочерний процесс сервера вызывает функцию

readline
, возвращает ошибку
ECONNRESET
и выводит следующее сообщение:

readline error: Connection reset by peer

Клиентский сокет не должен проходить через состояние ожидания TIME_WAIT, даже если клиент выполняет активное закрытие.

7.4. Первый клиент вызывает функции

setsockopt
,
bind
и
connect
. Но если второй клиент вызовет функцию
bind
между вызовами функций
bind
и
connect
первого клиента, возвращается ошибка
EADDRINUSE
. Но как только первый клиент установит соединение с собеседником, вызов функции
bind
второго клиента будет работать, поскольку сокет первого клиента уже присоединен. В случае возвращения ошибки
EADDRINUSE
второму клиенту следует вызывать
bind
несколько раз, а не останавливаться при появлении первой ошибки — это единственный способ справиться с данной ситуацией.

7.5. Запускаем программу на узле без поддержки многоадресной передачи (MacOS X 10.2.6).

macosx % <b>sock -s 9999 &amp;</b> <i>запускаем первый сервер с универсальным адресом</i>

[1] 29697

macosx % <b>sock -s 172.24.37.78 9999</b> <i>пробуем второй сервер, но без -А</i>

can't bind local address: Address already in use

macosx % <b>sock -s -A 172.24.37.78 9999 &amp;</b> <i>пробуем опять с -A: работает</i>

[2] 29699

macosx % <b>sock -s -A 127.0.0.1 9999 &amp;</b> <i>третий сервер с -A; работает</i>

[3] 29700

macosx % <b>netstat -na | grep 9999</b>

tcp4 0 0 127.0.0.1.9999     *.* LISTEN

tcp4 0 0 206.62.226.37.9999 *.* LISTEN

tcp4 0 0 *.9999             *.* LISTEN

7.6. Теперь попробуем проделать то же на узле с поддержкой многоадресной передачи, но без поддержки параметра

SO_REUSEADDR
(Solaris 9).

Перейти на страницу:
Комментариев (0)
название