2010-07-29 3 views
9

Пару дней назад мне пришлось исследовать проблему, когда мое приложение показывало аномально высокое использование ЦП, когда оно (по-видимому) находилось в состоянии ожидания. Я проследил проблему до цикла, который должен был блокировать вызов recvfrom, в то время как сокет был установлен в O_NONBLOCK -ing, что привело к блокировке вращения. Существует два способа решения проблемы: установите сокет на блокировку или опрос доступных данных в сокете, используя poll или select. Я выбрал первое, поскольку это было проще. Но мне интересно, почему кто-то создаст неблокирующий сокет, а затем опросит его отдельно. Разве блокирующий сокет не делает то же самое? Каковы случаи использования, в которых можно использовать неблокирующую сокет и комбинацию опросов? Существуют ли какие-либо преимущества для этого в общих случаях?Неблокирующий сокет с опросом

ответ

7

Использование poll() или select() с неблокируемому дескриптора файла дает два преимущества:

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

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

Второе преимущество - это вариант использования убийцы для select() и друзей. Это означает, что вы можете обрабатывать несколько соединений сокетов, а также стандартный ввод и стандартный вывод и, возможно, ввода-вывода файлов, все с одним потоком управления.

1

, что приводит к блокировке спина.

Это состояние обычно называется плотной петлей.

Существует два способа решения проблемы: установить сокет на блокировку или опрос доступных данных в сокете с помощью опроса или выбора. Я выбрал первое, поскольку это было проще.

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

В противном случае, да, переход в режим блокировки является самым простым решением.

Лучший обратной совместимости решение было бы перед вызовом recvfrom() использовать poll() ждать гнезда, чтобы стать читаемым. Таким образом, другие части кода будут работать точно так же, как и раньше.

Но мне интересно, почему кто-то создаст неблокирующий сокет, а затем опросит его отдельно. Разве блокирующий сокет не делает то же самое?

Для случая recvfrom() мне не известна большая разница.

В каких случаях используются неблокирующие сокеты и комбинация опросов? Существуют ли какие-либо преимущества для этого в общих случаях?

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

0

Всегда лучше делать сокеты как nonblocking, потому что даже блокирующий сокет становится готовым к тому времени (когда данные поступают, но имеет контрольную сумму и что отбрасывается) - даже если нет данных для чтения. Так что сделайте это nonblocking, дождитесь доступности данных через опрос, затем прочитайте. Я думаю, что это главное преимущество.

1

Я публикую здесь, потому что, хотя вопрос старый. Он как-то появился в моем поиске Google и определенно не получил должного ответа.

Принятый ответ просто подчеркивает два преимущества использования неблокирующих сокетов, но на самом деле не вникает в детали или не отвечает на реальный вопрос.

  • ПРИМЕЧАНИЕ: К сожалению, большинство интерактивных «обучающих программ» или фрагментов кода имеют только блокирующий код сокета, поэтому знание неблокирующих сокетов менее распространено.

Что касается того, когда вы используете его по сравнению с другим ... в целом блокирующие сокеты используются только в онлайн-фрагментах кода. Во всех (хороших) производственных приложениях используются неблокирующие сокеты. Я не осведомлен, если вы знаете о реализации, которая использует блокирующие сокеты (и, конечно, это очень хорошо возможно в сочетании с потоками) - или давайте более конкретным, использующим блокирующие сокеты в одном потоке - пожалуйста, позвольте я знаю.

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

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

+0

Не 'select' и' poll' устраняет проблему блокировки, сообщая вам, что конкретная операция ** не будет блокировать ** при выполнении этой операции? Неужели эти хорошие производственные приложения все еще блокируют блокировку? – TheBuzzSaw

+0

@ TheBuzzSaw Я не уверен, что я понимаю вопрос. Мы исключаем использование одного сокета здесь, поэтому у вас есть набор дескрипторов файлов, которые вы используете для каждого вызова, и он не выбран, а фактический вызов recv, который блокирует, ожидая получения данных. –

+0

Я говорю, что когда программа использует 'select' для мультиплексирования более дюжины сокетов, обычно нет смысла помещать эти сокеты в неблокирующий режим, потому что вызов' select' определяет, какие действия не будут блокироваться. Если 'select' возвращает и скажет мне, что сокет' 45' не будет блокировать чтение, я могу вызвать 'recv', не опасаясь блока, не так ли? – TheBuzzSaw

Смежные вопросы