Эффективное программирование TCP-IP


         

ошибка вызова readline: Connection reset


bsd: $ tcprw localhost 9000

hello.

получено сообщение 1

Здесь сервер был остановлен.

hello again

tcprw: ошибка вызова readline: Connection reset by peer (54)

Клиент игнорирует ошибку, но

TCP уже разорвал соединение.

hello for the last time

Broken pipe   Клиент получает сигнал SIGPlPE

и завершает работу.

bsd: $

Когда вводится вторая строка, клиент, как и раньше, немедленно извещает ошибке (соединение сброшено сервером), но не завершает сеанс. Он еще раз обращается к fgets, чтобы получить очередную строку для отправки серверу стоит внести эту строку, как клиент тут же прекращает работу, и командный интерпретатор сообщает, что выполнение было прервано сигналом SIGPIPE. В этом случае при втором обращении к send, как и прежде, TCP послал RST, но вы не обратили на него внимания. Однако после получения RST клиентский ТСP разорвал соединение, поэтому при попытке отправить третью строку он немедленно завершает клиента, посылая ему сигнал SIGPIPE. Хронология такая же как на рис. 2.19. Разница лишь в том, что клиент «падает» при попытке записи, а не чтения.

Правильно спроектированное приложение, конечно, не игнорирует ошибки, такая ситуация может иметь место и в корректно написанных программах. Предположим, что приложение выполняет подряд несколько операций записи без промежуточного чтения- Типичный пример - FTP. Если приложение на другом конце «падает», то TCP посылает сегмент FIN. Поскольку данная программа только пишет, но не читает, в ней не содержится информация о получении этого FIN. При отправке следующего сегмента TCP на другом конце вернет RST. А в программе опять не будет никаких сведений об этом, так как ожидающей операции чтения нет. При второй попытке записи после краха отвечающего конца программа получит сигнал SIGPIPE, если этот сигнал перехвачен или игнорируется - код ошибки EPIPE.

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

Поведение зависит от соотношения времен. Например, если снова прогнать первый тест, запустив сервер на машине spare, а клиента - на машине bsd, то получается следующее:

bsd: $ tcprw localhost 9000

hello

получено сообщение 1    Это печатается после пятисекундной

задержки.

Здесь сервер был остановлен.

hello again

tcprw: сервер завершил работу

bsd: $

На этот раз клиент обнаружил конец файла, посланный в результате остановки сервера. RST по-прежнему генерируется при отправке второй строки, но из-за задержек в сети клиент успевает вызвать readline и обнаружить конец файла еще до того, как хост bsd получит RST. Если вставить между строками 14 и 15 в листинге 2.21 строчку

sleep( 1 );

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


Содержание  Назад  Вперед





Forekc.ru
Рефераты, дипломы, курсовые, выпускные и квалификационные работы, диссертации, учебники, учебные пособия, лекции, методические пособия и рекомендации, программы и курсы обучения, публикации из профильных изданий