LINUX.ORG.RU

socket & write()


0

0

Здравствуйте. В каком случае вызов write на сокете может заблокировать программу? read() понятно, что если нету данных. а write() ? Я к тому, что следует ли перед вызовом проверить сокет poll()-м на возможность записи или это лишнее?

anonymous

> Я к тому, что следует ли перед вызовом проверить сокет poll()-м на возможность записи или это лишнее?

Следует.

write() запросто может заблокировать, если с другой стороны read() не делать.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Ладно, опишу проблему более детально: общаюсь с сервером - сперва он мне строку кидает, затем я ему. Вот и заинтересовало - если он мне кинул строку, и я ее получил - то он наверняка меня уже ждет, и я могу сразу же начать писать в сокет, без промежуточного poll(), а затем уже вызвать его для проверки на чтение. Или все же не стоит так делать, и вызывать poll() для проверки на запись?

anonymous
()
Ответ на: комментарий от Die-Hard

>write() запросто может заблокировать, если с другой стороны read() не делать.

Чисто по-человечески интересно: если сокет неблокирующий, то это все равно возможно? Или "неблокируемость" относится только к чтению?

anonymous
()
Ответ на: комментарий от anonymous

> Чисто по-человечески интересно: если сокет неблокирующий, то это все равно возможно? Или "неблокируемость" относится только к чтению?

флаг O_NONBLOCK относится и к записи и к чтению.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от anonymous

anonymous (*) (21.09.2005 7:39:28):

> ...если он мне кинул строку, и я ее получил - то он наверняка меня уже ждет,

Не обязательно!

Может сеть зависнуть, может сервер зависнуть на сисколе (под большой нагрузкой -- запросто!), может еще что...

Я бы всегда делал poll()

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Да - самое простое - заполненность сетевых буферов. write() при этом будет ждать освобождения, по идее.

UncleAndy ★★★
()
Ответ на: комментарий от Die-Hard

Ok, спасибо.

А как именно poll() узнает, что запись не будет заблокирована? Это в кратце можно рассказать? Про чтение то вроде понятно, даже по netstat видно когда данные есть, а запись мне непонятна.

anonymous
()
Ответ на: комментарий от anonymous

> А как именно poll() узнает, что запись не будет заблокирована?

никак и никогда. это уже обсуждалось здесь, поищите.

poll() нужно воспринимать как указание, что имеет смысл
произвести попытку i/o, и эта попытка, возможно, не будет
блокирована. поэтому имеет смысл использовать poll() +
O_NONBLOCK.

idle ★★★★★
()
Ответ на: комментарий от idle

Мне кажеться, что вы правы. Однако, например, Die-Hard утверждает, что использовать O_NONBLOCK вместе с select/pool не имеет смысла в общем случае.

UncleAndy ★★★
()
Ответ на: комментарий от UncleAndy

я склонен считать что idle более прав

cvv ★★★★★
()
Ответ на: комментарий от UncleAndy

UncleAndy:

> Однако, например, Die-Hard утверждает, что использовать O_NONBLOCK вместе с select/pool не имеет смысла в общем случае.

Может, я и не прав...

Источник моих знаний:

1. man select: ...more precisely, to see if a read will not block ... those in writefds will be watched to see if a write will not block...

2. За многолетнюю практику со мной ни разу не случалось, чтобы select() меня подвел. Каждый раз, когда i/o блокировалось после select'а, объяснялся ошибками в программе. Причем мне приходилось писать довольно сложную логику на многочисленных пайпах и сокетах, месяцами интенсивно работающих в синхронном режиме.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

пусть poll() сообщает что можно писать. но он не скажет
_сколько_ писать, возможно всего один байт, а ты передашь
ему 2. или кто-то другой уже успел всунуть данные в сокет.
или пропала память в окошке межде poll() и write().

c чтением проще, но тоже проблемы: другой поток может
увести даннные, ты читаешь больше, чем пришло данных.

idle ★★★★★
()
Ответ на: комментарий от idle

2idle:

Ну, это -- другое дело!

Это как раз те самые случаи, про которые я говорил "немногие, когда нужен неблокирующий I/O".

На самом деле, это вопрос больше самодисциплины. Это как с goto. По моим наблюдениям (над собой), почти всякий раз, когда возникало искушение поставить O_NONBLOCK, находилось более "правильное" решение с блокирующим I/O.

Кстати, случаи

> возможно всего один байт, а ты передашь ему 2.

и

> ты читаешь больше, чем пришло данных

предусмотрены, просто операторы write()/read() вернут число, меньшее последнего аргумента. Блокировка наступает, если read() не может прочитать ни одного байта и при этом не EOF.

То же самое с write().

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Кстати, случаи
> ...
> предусмотрены, просто операторы write()/read() вернут число,
> меньшее последнего аргумента.

для того же pipe, например, это не совсем верно, чтение
вернет меньше байт, если !PIPE_WAITING_WRITERS(), хотя
по сути ты прав: если в pipe или socket что-то есть, это
будет получено без блокировки "надолго".

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

кроме того, не забываем про SO_RCVLOWAT, MSG_WAITALL.

для записи это совсем не верно: будет спать.

idle ★★★★★
()
Ответ на: комментарий от idle

> но я не знаю гарантируется ли такое поведение стандартами (особенно если иметь в виду устройства всякие), я бы не стал закладываться.

Ну, драйвер можно написать сколь угодно криво, но тогда и O_NONBLOCK может не помочь!

Про пайпы, стримы и файлы стандарты прописаны. Например, у меня под руками есть The Single UNIX (R) Specification, Version 2:

If some process has the pipe open for writing and O_NONBLOCK is clear, read() will block the calling thread until some data is written or the pipe is closed by all processes that had the pipe open for writing.

When attempting to read a file (other than a pipe or FIFO) that supports non-blocking reads and has no data currently available ...

The use of the O_NONBLOCK flag has no effect if there is some data available.

> для записи это совсем не верно: будет спать.

Да, тут я подзабыл. Чтобы write() вернул меньше, надо как раз O_NONBLOCK ставить, я и сам так делаю, сейчас посмотрел :)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> The use of the O_NONBLOCK flag has no effect if there
> is some data available.

Ok, буду знать, thanks.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.