Использование обеих неблокирующих розеток и select
- правильный путь.Возвращение EWLOULDBLOCK не означает, что весь поток данных закончен, получая, это означает, что мгновенно нечего читать прямо сейчас.Это именно то, что вы хотите, потому что это означает, что read
не будет ждать даже полсекунды, чтобы появилось больше данных.Если данные не сразу доступны, они вернутся.
Теперь, очевидно, это означает, что вам нужно будет несколько раз вызвать read
, чтобы получить полные данные.Общий формат для этого - цикл выбора.В псевдокоде:
do
select ( my_sockets )
if ( select error )
handle_error
else
for each ( socket in my_sockets ) do
if ( socket is ready ) then
nonblocking read from socket
if ( no data was read ) then
close socket
remove socket from my_sockets
endif
endif
loop
endif
loop
Идея состоит в том, что select
скажет вам, какие сокеты имеют данные для чтения прямо сейчас .Если вы прочитаете один из этих сокетов, вы гарантированно либо получите данные, либо получите возвращаемое значение 0, указывающее, что удаленный конец закрыл сокет.
Если вы используете этот метод, вы никогда не застрянете в вызове read
, который не читает данные, в течение любого промежутка времени.Операция блокировки - это вызов select
, и вы также можете выбрать перезаписываемые сокеты, если вам нужно писать, и установить тайм-аут, если вам нужно что-то делать периодически.