Разъем C: отправляет ли ожидание завершения recv? - PullRequest
7 голосов
/ 26 августа 2010

Я использую блокирующие C розетки на Windows. Я использую их для отправки обновлений данных с сервера на клиент и наоборот. Я отправляю обновления с высокой частотой (каждые 100 мс). Будет ли функция send() ждать, пока получатель recv() получит данные, прежде чем завершится?

Полагаю, нет, если я хорошо понимаю справочную страницу:

«Успешное завершение send () не гарантирует доставку сообщения.»

Так что же произойдет, если у одного будет 10 send() случаев, а у другого только 1 recv()?

Нужно ли мне использовать какую-то систему подтверждения?

Ответы [ 5 ]

11 голосов
/ 27 августа 2010

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

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

Если удаленный конец работает медленно, исходящая очередь заполняется данными, а отправка блокируется, пока не останется места для размещения новых данных в исходящей очереди.

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

Для UDP, я думаю, само собой разумеется, что какой-то способ сообщения о том, что было или не было получено, является обязательным.

8 голосов
/ 26 августа 2010

send() блокируется до тех пор, пока операционная система (ядро) не соберет данные и не поместит их в буфер исходящих данных. Он не ждет, пока другой конец не получит данные.

2 голосов
/ 26 августа 2010

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

Если вы используете UDP, то все это не так - данные могут поступать не по порядку, или отбрасываться, и никогда не доставляться вообще. Если вы заботитесь обо всех получаемых данных, вам просто необходимо создать какую-то собственную систему подтверждения поверх самого UDP.

1 Конечно, есть ограничение на гарантию - если сетевой кабель обрезается (или что-то еще), пакеты не будут доставлены, но вы по крайней мере получите сообщение об ошибке, сообщающее вам что связь была потеряна.

0 голосов
/ 27 июня 2017

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

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

0 голосов
/ 26 августа 2010

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

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

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