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

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

Например, это - простой пример общей схемы:

int send_all(int sock, unsigned char *buffer, int len) {
  int nsent;

  while(len > 0) {
    nsent = send(sock, buffer, len, 0);
    if(nsent == -1) // error
      return -1;

    buffer += nsent;
    len -= nsent;
  }
  return 0; // ok, all data sent
}

Даже страница справочника BSD упоминает это

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

То, которое указывает, что мы должны предположить, что отправляют, может возвратиться, не отправляя все данные. Теперь я нахожу это скорее поврежденным, но даже W. Richard Stevens предполагает, что это в его стандартном справочнике о сетевом программировании, не в начинающихся главах, но более усовершенствованных примерах использует его собственное записанное (запишите все данные), функция вместо того, чтобы назвать запись.

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

Я имею в виду в примере кода выше, что произойдет, если отправят, возвраты с меньшим количеством отправленных данных то, что это назовут правильным снова с новым запросом. Что изменилось начиная с последней возможности? В макс. нескольких сотнях ЦП циклы передали так буфер, все еще полно. Если отправляют, теперь принимает данные, почему could'nt они принимают его прежде?

Иначе мы закончим upp неэффективным циклом, где мы пытаемся отправить данные по сокету, который не может принять данные и продолжать пробовать, или иначе?

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

20
задан Ernelli 11 April 2010 в 21:14
поделиться

3 ответа

В приведенном выше описании отсутствует то, что в Unix системные вызовы могут прерываться сигналами. Именно по этой причине блокировка send (2) может вернуть короткий счетчик.

21
ответ дан 30 November 2019 в 01:02
поделиться

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

Это означает, что вам не нужно беспокоиться о том, что при записи данных в сокет они не будут доставлены.Это означает, что драйвер ядра может позволить себе сказать: «У меня есть место для хранения этого, принесите!» и дать программе пользовательского режима быстрый возврат к более важным вещам, например, к обновлению пользовательского интерфейса.

Хорошая вещь. Если по какой-то причине ваша гарантия доставки должна быть сильнее, чем это, может быть, 12 девяток, тогда вам не следует использовать TCP. Сделано, гуглит "надежный UDP" хорошо. Хотя его изобретают снова и снова. Удачи!

0
ответ дан 30 November 2019 в 01:02
поделиться

По сути, поведение просто добавляет гибкости.

Рассмотрим, что произойдет, если во внутренних буферах отправки есть место еще для 300 байт, а вы просите send() отправить 800 байт.

Как правило, происходит так: программа принимает первые 300 байт и помещает их в буфер сокета, а затем возвращается. Если вы действительно хотите блокировать отправку, пока не пройдут все 800 байт, то вы просто повторно вызовете send() для последних 500 байт, и он заблокируется (поскольку буфер отправки теперь заполнен). С другой стороны, если вы хотите сделать что-то еще сейчас, а оставшиеся 500 байт попытаться отправить позже, вы можете сделать и это.

2
ответ дан 30 November 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: