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 % sock -s 9999 &
[1] 29697
macosx % sock -s 172.24.37.78 9999
can't bind local address: Address already in use
macosx % sock -s -A 172.24.37.78 9999 &
[2] 29699
macosx % sock -s -A 127.0.0.1 9999 &
[3] 29700
macosx % netstat -na | grep 9999
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).
solaris % sock -s -u 8888 &
[1] 24051
solaris % sock -s -u 8888
can't bind local address: Address already in use
solaris % sock -s -u -A 8888 &
solaris % netstat -na | grep 8888
*.8888 Idle
* 8888 Idle
В этой системе задавать параметр SO_REUSEADDR
было необходимо только для второго связывания. Наконец, запускаем сценарий в MacOS X 10.2.6, где поддерживается как многоадресная передача, так и параметр SO_REUSEPORT
. Сначала пробуем использовать SO_REUSEADDR
для обоих серверов, но это не работает.
macosx % sock -u -s -A 7777 &
[1] 17610
macosx % sock -u -s -A 7777
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии