Неблокирующие розетки с Select - PullRequest
3 голосов
/ 06 января 2010

Я не понимаю, в чем разница между вызовом recv () на неблокирующем сокете и блокирующим сокетом после ожидания вызова recv () после того, как select возвращает, что он готов к чтению. Мне кажется, что блокирующий сокет никогда не заблокируется в этой ситуации.
Кроме того, я слышал, что одной из моделей использования неблокирующих сокетов является попытка сделать вызовы (recv / send / etc) через некоторое время, а не использовать что-то вроде select. Этот метод кажется медленным и расточительным по сравнению с использованием чего-то вроде select (но тогда я не получаю цели неблокирования вообще, как описано выше). Это обычное явление в сетевом программировании сегодня?

Ответы [ 4 ]

3 голосов
/ 06 января 2010

Существует большой обзор всех различных вариантов выполнения операций ввода-вывода большого объема, которые называются Проблема C10K . В нем достаточно полный обзор множества различных вариантов, по крайней мере, по состоянию на 2006 год.

Цитирование из него, на тему использования select на неблокирующих сокетах:

Примечание: особенно важно помнить, что уведомление о готовности от ядра - только подсказка; дескриптор файла может быть не готов, когда вы пытаетесь читать с него. Вот почему важно использовать неблокирующий режим при использовании уведомления о готовности.

И да, вы можете использовать неблокирующие сокеты, а затем иметь цикл, который ждет, если ничего не готово, но это довольно расточительно по сравнению с использованием чего-то вроде select или одной из более современных замен (epoll, kqueue и т. Д.). Я не могу придумать причину, по которой кто-то на самом деле хотел бы сделать это; все опции типа select имеют возможность установить тайм-аут, так что вы можете проснуться через определенное время, чтобы выполнить какое-то регулярное действие. Я полагаю, что если вы выполняете что-то достаточно интенсивное использование процессора, например, запускаете видеоигру, вы, возможно, захотите никогда не спать, а вместо этого продолжать вычисления, периодически проверяя ввод / вывод с использованием неблокирующих сокетов.

1 голос
/ 06 января 2010

Средства select, poll, epoll, kqueue и т. Д. Предназначены для нескольких сценариев обработки дескрипторов сокетов / файлов. Представьте себе загруженный веб-сервер с сотнями одновременно подключенных сокетов. Как бы вы узнали, когда read и из какого сокета, не блокируя все?

0 голосов
/ 06 января 2010

По вашему первому вопросу, в этом сценарии нет разницы. Разница лишь в том, что они делают, когда нечего читать. Поскольку вы проверяете это перед вызовом recv (), вы не увидите никакой разницы.

Что касается второго вопроса, то, как я вижу это во всех библиотеках, это использовать select, poll, epoll, kqueue для проверки наличия данных. Метод select является самым старым и наименее желательным с точки зрения производительности (особенно для управления большим количеством соединений).

0 голосов
/ 06 января 2010

Если вы вызываете read на неблокирующем сокете, он немедленно вернется, если с момента последнего вызова read не было получено никаких данных. Если у вас было только read, и вы хотели подождать, пока не появятся доступные данные, вам придется занято ждать . Это тратит впустую CPU.

poll и select (и друзья) позволяют вам спать, пока нет данных для чтения (или записи, или получения сигнала и т. Д.).

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

...