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

       

Операция записи с точки зрения приложения


Когда пользователь выполняет запись в TCP-соединение, данные сначала копируются из буфера пользователя в память ядра. Дальнейшее зависит от состояния соединения. TCP может «решить», что надо послать все данные, только часть или ничего не посылать. О том, как принимается решение, будет сказано ниже. Сначала рассмотрим операцию записи с точки зрения приложения.

Хочется думать, что если операция записи n байт вернула значение n, то все эти n байт, действительно, переданы на другой конец и, возможно, уже подтверждены. Увы, это не так. TCP посылает столько данных, сколько возможно (или ничего), и немедленно возвращает значение n. Приложение не определяет, какая часть данных послана и были ли они подтверждены.

В общем случае операция записи не блокирует процесс, если только буфер передачи TCP не полон. Это означает, что после записи управление почти всегда быстро возвращается программе. После получения управления нельзя ничего гарантировать относительно местонахождения «записанных» данных. Как упоминается в совете 9, это имеет значение для надежности передачи данных.

С точки зрения приложения данные записаны. Поэтому, помня о гарантиях доставки, предлагаемых TCP, можно считать, что информация дошла до другого конца. В действительности, некоторые (или все) эти данные в момент возврата из операции записи могут все еще стоять в очереди на передачу. И если хост или при­ложение на другом конце постигнет крах, то информация будет потеряна.

Примечание:  Если отправляющее приложение завершает сеанс аварийно, то TCP все равно будет пытаться доставить данные.

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

Примечание: Строго говоря, это неверно. Обычно данные находятся в буфере в пространстве ядра до того момента, пока не произойдет сброс буферов на диск. Поэтому если до этого момента система «упадет», то данные вполне могут быть потеряны. Но суть в том, что после возврата из write уже не будет никаких сообщений об ошибках. Можно признать потерю не сброшенных на диск данных неизбежной, но не более вероятной, чем отказ самого диска.


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

  • неверный дескриптор сокета;


  • файловый дескриптор указывает не на сокет (в случае вызова send и родственных функций);


  • указанный при вызове сокет не существует или не подсоединен;


  • в качестве адреса буфера указан недопустимый адрес.


  • Причина большинства этих проблем - ошибка в программе. После заверше­ния стадии разработки они почти не встречаются. Исключение составляет код ошибки EPIPE (или сигнал SIGPIPE), который свидетельствует о сбросе соедине­ния хостом на другом конце. Условия, при которых такая ошибка возникает, обсуждались в совете 9 при рассмотрении краха приложения-партнера.

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


    Содержание раздела