Неблокирующая запись TCP (2) успешно выполнена, но запрос не отправлен - PullRequest
1 голос
/ 25 февраля 2009

Я вижу, что небольшой набор сообщений, записанных в неблокирующий сокет TCP с использованием write (2), не виден на интерфейсе источника и также не получен адресатом.

В чем может быть проблема? Есть ли способ, которым приложение может обнаружить это и повторить попытку?

while (len > 0) {
    res = write (c->sock_fd, tcp_buf, len);
    if (res < 0) {
      switch (errno) {
        case EAGAIN:
        case EINTR:
        <handle case>
        break;
        default:
        <close connection>
      }
    }
    else {
      len -= res;
    }
}     

Ответы [ 3 ]

3 голосов
/ 25 февраля 2009

Неблокирующая write(2) означает, что при любых трудностях звонок будет возвращен. Правильный способ определить, что произошло, - проверить возвращаемое значение функции.

Если возвращается -1, проверьте errno. Значение EAGAIN означает, что write сделал не произошло, и вам придется сделать это снова.

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

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

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

и выводы таковы:

Лучший совет - отправить информацию о длине и заставить удаленную программу активно подтверждать, что все данные были получены.

Также описывается взлом для Linux.

1 голос
/ 26 мая 2009

Вы хотите прочитать об опции TCP_NODELAY и характере буфера отправки TCP.

1 голос
/ 25 февраля 2009

write () возвращает количество записанных байтов, это может быть меньше, чем количество отправленных байтов, и даже 0! Убедитесь, что вы проверили это и повторно передали все, что было отброшено (из-за нехватки места на буфере на сетевой карте или что-то еще)

...