Выяснение, было ли доставлено сообщение через tcp. - PullRequest
10 голосов
/ 07 октября 2009

Когда я отправляю () / write () сообщение через поток tcp, как я могу узнать, были ли эти байты успешно доставлены?

Получатель подтверждает получение байтов через tcp, поэтому стек tcp отправителей должен знать.

Но когда я посылаю () несколько байтов, send () немедленно возвращается, даже если пакет (пока) не может быть доставлен, я проверил это на Linux 2.6.30, используя strace на netcat, вытаскивая сетевой кабель перед отправкой несколько байтов.

Я просто занимаюсь разработкой приложения, в котором очень важно знать, доставлено ли сообщение, но реализация функций tcp («ack for message # 123») выглядит неловко, должен быть лучший способ.

Ответы [ 6 ]

21 голосов
/ 08 октября 2009

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

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

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

8 голосов
/ 07 октября 2009

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

Гораздо лучше отправить ваш «пакет», будь то строка, сериализованный объект или двоичные данные, и заставить получателя делать все необходимые проверки, чтобы убедиться, что он там, и затем отправить обратно подтверждение.

6 голосов
/ 07 октября 2009

Протокол TCP очень старается, чтобы убедиться, что ваши данные поступают. Если возникнет проблема с сетью, данные будут переданы несколько раз. Это означает, что все, что вы отправляете, буферизуется, и нет своевременного способа убедиться, что он прибыл (через 2 минуты будет тайм-аут, если сеть не работает).

Если вам нужна быстрая обратная связь, используйте протокол UDP. Он не использует никаких издержек TCP, но вы должны решить все проблемы самостоятельно.

3 голосов
/ 08 октября 2009

Даже если он достиг уровня TCP, нет гарантии, что он не будет помещен в буфер приложения, тогда приложение завершит работу до того, как сможет его обработать. Используйте подтверждение, это то, что делает все остальное (например, SMTP)

3 голосов
/ 07 октября 2009

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

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

A: Send 450 Bytes
B: Recv 450 Bytes
B: Send 'I got 450 Bytes'
A: Recv 'B got the full message'
A: Continue
1 голос
/ 07 октября 2009

Звучит так: SCTP может быть чем-то, на что можно посмотреть; Я думаю, что это должно поддержать то, что вы хотите. Кажется, альтернативой является переключение на UDP, и если вы переключаете протоколы в любом случае

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