В man
страницах Linux о write()
он заявил, что в случае EINTR
или EAGAIN
write()
вернется -1
. При выполнении read()
можно повторить попытку, если такие ошибки встречаются. Что делать в таких ситуациях при выполнении write()
?как писать в сокет правильно
ответ
Насколько я знаю, способ обработки таких случаев включает в себя завершение вызова write()
внутри функции, которая проверяет возвращаемое значение, а также переменную errno
.
EAGAIN
Случаи, как и EINTR
указывают на ситуации, когда write()
был неудачным из-за какой-то сигнал прервал его или O_NONBLOCK
был установлен, но write()
будет блокировать. Это означает, что вы можете повторить попытку write()
, проверив состояние errno
.
Я не уверен,, однако, если это гарантирует, что write()
будет в конечном итоге добиться успеха, если вы настаиваете (и, конечно, если вы не получаете никакой иной errno
статус).
Вы могли бы сделать что-то вроде
ssize_t insist_write(int fd, const void * buff, size_t cnt)
{
ssize_t ret;
size_t original_cnt = cnt;
while (cnt > 0)
{
ret = write(fd, buff, cnt);
if (ret < 0)
{
// EINTR for interrupted writes, EAGAIN - EWOULDBLOCK for file/socket
// blocking case (see man page)
if ((errno != EINTR) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
return ret;
else
ret = 0;
}
// update buff and remaining bytes to write
buff += ret;
cnt -= ret;
}
return original_cnt;
}
Я также видел код, где выше случае обрабатываемый делают
if (ret < 0) { return ret; }
вместо того, что я написал, это означает, что такие случаи будут обрабатываться на на основе каждого приложения (в одном из таких примеров указывается максимальное количество попыток write()
перед возвратом -1
).
Это правда, что вы можете обернуть звонки write()
, проверив для EINTR
или EAGAIN
. Простой цикл попробовать write()
снова в тех случаях, предлагается в this вопрос, и может хорошо работать:
Вы можете повторить попытку в случае EINTR.
Вы можете получить только EAGAIN/EWOULDBLOCK
если вы в не- режим блокировки, и в этих случаях нецелесообразно просто повторять в цикле. Вы должны select()
до тех пор, пока сокет не станет доступен для записи, и затем повторите попытку. Это может произойти только тогда, когда одноранговый узел что-то читает, поэтому не рекомендуется записывать циклы процессора на отправляющем конце.
- 1. как писать байты в сокет сервера
- 2. Как правильно получить сокет
- 3. Как правильно писать UNPIVOT?
- 4. Как правильно читать/писать UNIX-сокеты?
- 5. Как правильно инкапсулировать сокет socket.io?
- 6. Как правильно закрыть неблокирующий сокет?
- 7. Как правильно писать API-интерфейсы
- 8. Как правильно писать жирные ссылки?
- 9. Как правильно писать тесты JUnit?
- 10. Как правильно писать регулярное выражение
- 11. Как правильно писать «Engine-X»?
- 12. Как правильно писать текст python
- 13. Правильно закрыть TCP-сокет
- 14. Как читать и писать в php-сокет в одной программе?
- 15. правильно писать класс библиотеки
- 16. файла писать не правильно
- 17. Как правильно писать в php? json
- 18. как правильно писать этот код в javascript
- 19. Как правильно писать несколько папок в Gulp?
- 20. Как правильно писать код в первый раз?
- 21. Как вы правильно используете «писать» в Applescript?
- 22. Android: Как правильно отправлять изображения через сокет
- 23. Как правильно закрыть сокет после исключения?
- 24. PHP обыкновение писать правильно Textfile
- 25. Как правильно писать Doctrine 2 DQL-запросы?
- 26. Как правильно писать PHP с многоязычными элементами?
- 27. Вложенный корпус: как я могу правильно писать?
- 28. Как правильно писать заголовки заголовков циклов?
- 29. Как правильно писать RabbitMQ Publisher на Java?
- 30. Ruby: Как правильно и эффективно писать комментарии?
Автор писал: «Я читаю страницы' man', и я понимаю, что если 'write()' fail с ошибкой 'EAGAIN' или' EINTR', я должен выполнить 'write()' again_ "no , не обязательно. Попробуйте еще раз. Это зависит от реализации, а страницы 'man' никогда не говорили ничего подобного. Его понимание и, следовательно, описание его вопроса неверны. – Barracuda