Как TCP / IP сообщает об ошибках? - PullRequest
1 голос
/ 08 октября 2008

Как протокол TCP / IP сообщает об ошибках, когда доставка пакета не удалась окончательно? Все API Socket.write (), которые я видел, просто передают байты в базовый выходной буфер TCP / IP и передают данные асинхронно. Как тогда TCP / IP должен уведомлять разработчика, если доставка пакета не удалась окончательно (то есть хост назначения больше не доступен)?

Любой протокол, который требует, чтобы отправитель ждал подтверждения от удаленного конца, получит сообщение об ошибке. Но что происходит с протоколами, когда отправителю не нужно читать байты из места назначения? TCP / IP просто молчит? Возможно, Socket.close () вернет ошибку? Говорит ли об этом спецификация TCP / IP?

Ответы [ 4 ]

5 голосов
/ 08 октября 2008

TCP / IP - это надежный протокол потока байтов. Все ваши байты попадут в получатель, или вы получите сообщение об ошибке.

Индикация ошибки будет иметь вид закрытой розетки. Независимо от того, какой шаблон связи (кто отправляет), если байты не могут быть доставлены, сокет закроется.

Итак, вопрос в том, как вы видите закрытие сокета? Если вы никогда не читаете, вы в конечном итоге получите ошибку при попытке записи в закрытый сокет (с ECONNRESET errno, я думаю).

Если вам нужно поспать или подождать ввода для другого дескриптора файла, возможно, вы захотите подождать в вызове select (), где вы включаете сокет в список источников, на которых вы ожидаете (даже если Вы никогда не ожидаете получить что-нибудь). Если select () указывает, что сокет готов к вызову чтения, вы можете получить возврат -1 (думаю, с ECONNRESET). EOF будет означать упорядоченное закрытие (другая сторона сделала shutdown () или close ().

Как отличить эту ошибку при закрытии (например, при выходе из другой программы)? Ошибочных значений может быть достаточно, чтобы отличить ошибку от упорядоченного закрытия.

Если вам требуется однозначное указание на проблему, вам, вероятно, потребуется создать какой-то протокол уровня приложения выше уровня сокетов. Например, короткое «подтверждающее» сообщение, отправленное получателем обратно отправителю. Тогда нарушение этого прикладного протокола более высокого уровня (отправитель не видел подтверждения) будет подтверждением того, что это была ошибка закрытия по сравнению с чистым закрытием.

4 голосов
/ 08 октября 2008

API сокетов не может сообщить автору точно, сколько байтов было получено, как было подтверждено партнером. Нет никаких гарантий, сделанных присутствием shutdown или close либо.

Спецификация TCP / IP ничего не говорит об интерфейсе приложения (который почти всегда является API сокетов).

SCTP - это альтернатива TCP, которая, среди прочего, пытается устранить эти недостатки.

0 голосов
/ 08 октября 2008

TCP основан на IP-протоколе, который является центральным элементом Интернета, обеспечивая большую часть функциональной совместимости, которая управляет маршрутизацией, которая определяет то, как получать пакеты от их источника к месту назначения. Протокол IP указывает, что сообщения об ошибках должны отправляться обратно отправителю по протоколу ICMP (Internet Control Message Protocol) в случае, если пакет не может попасть отправителю. Некоторые из этих причин включают в себя поле времени жизни (TTL), уменьшенное до нуля, что часто означает, что пакет застрял в цикле маршрутизации или пакет отбрасывается из-за конфликта коммутатора, вызывающего переполнение буфера. Как уже говорили другие, именно Socket API отвечает за передачу этих ошибок на уровне IP вплоть до приложения, взаимодействующего с сетью на уровне TCP.

0 голосов
/ 08 октября 2008

В C, если вы пишете в сокет, в котором произошел сбой с помощью send (), вы получите количество отправленных байтов. Если это не соответствует количеству байтов, которые вы намеревались отправить, у вас есть проблема. Но также, когда вы пишете в сбойный сокет, вы получаете SIGPIPE обратно. Перед началом работы с сокетом необходимо иметь обработчик сигналов, который будет предупреждать вас, когда вы получите SIGPIPE.

Если вы читаете из сокета, вам действительно следует обернуть его сигналом тревоги, чтобы вы могли тайм-аут. Например, «alarm (timeout_val); recv (); alarm (0)». Проверьте код возврата recv, и если он равен 0, это означает, что соединение было закрыто. Отрицательный результат возврата указывает на сбой чтения, и вам нужно проверить errno.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...