Что пишет (2) возвращение нулевого значения и буду ли я в итоге делать успехи (ненулевой результат)?

У меня есть сокет поверх TCP, в который я пишу программу C ++ 03. В некоторых случаях я получаю нулевой результат возврата из write (). Справочная страница write (2) частично описывает:

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

Итак, действительно ли ноль означает отсутствие ошибки, и я должен просто вызвать write снова, пока все, что я написал, не было написано? Другими словами, должен ли я просто обращаться с нулем, как я это делаю для частичной записи, где число записанных байтов меньше, чем count Я прошел, чтобы написать и просто продолжать пытаться, пока я не достигну в общей сложности count байты написаны?

Я хочу убедиться, что не попаду в бесконечный цикл с записью, возвращающей ноль непрерывно и никогда не прогрессирующей. Должен ли я вызывать select (), чтобы убедиться, что файловый дескриптор готов перед вызовом write? У меня включена блокировка дескриптора файла.

2

Решение

Хотя в теории это, вероятно, либо пройдет, либо получит ошибку в конце концов, я бы на всякий случай создал некоторую защиту от бесконечных циклов.

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

Итак, я бы сделал что-то вроде этого:

int write_zero_count = 0;

while(not_all_written)
{
int res;
res = select(...);
... check if we can write, etc ...
res = write(...);
if (res == 0)
{
write_zero_count++;
if (write_zero_count > max_zero_writes)
{
error("Got many writes that sent zero bytes, not good");
.... do other stuff to log and recover from error or exit? ...
}
}
else
{
write_zero_count = 0;
}
}
1

Другие решения

write() или же send() в режиме блокировки можно вернуть только ноль, если указать нулевую длину. Это почти наверняка ошибка программирования с вашей стороны.

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

В неблокирующем режиме запись нулевой длины означает, что буфер отправки сокета заполнен. Когда вы получите это, вы должны начать выбирать этот сокет как writefd и повторить запись, когда сокет станет доступным для записи. Если это удастся, прекратите выделять его как writefd. Обычно вы вообще не должны использовать наборы writefd, так как сокеты почти всегда готовы к записи, за исключением случаев, когда здесь, поэтому селектор просто вернется немедленно.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector