Многопоточный сервер с boost asio

Я рассматриваю возможность написания многопоточного TCP-сервера с использованием Boost ASIO. Я прочитал учебные пособия и просмотрел некоторые примеры и просто хочу проверить правильность моего понимания.

Сервер будет принимать соединения, а затем обслуживать запросы от нескольких клиентов.

Мое понимание заключается в следующем:

  1. Сервер использует «один io_service и пул потоков, вызывающий io_service::run()»
  2. Все потоки вызывают io_service::run().
  3. Вызовы io_service::run() не находятся внутри нити, поэтому обработчики завершения могут работать одновременно.
  4. При поступлении запроса выбирается один из потоков, вызывается его обработчик чтения
  5. Может поступить другой запрос, запускающий обработчик чтения во втором потоке.
  6. Когда один из потоков завершает обработку запроса, он вызывает async_write из strand
  7. Другой поток также завершает обработку своего запроса, он также вызывает async_write из цепочки.
  8. Записи в io_service сериализуются через strand, поэтому они потокобезопасны.
  9. Когда операция записи завершается, поток вызывает async_read()
  10. Этот вызов не защищен strand, и поток будет использоваться для обработки запросов.

Правильно ли я понимаю? Уязвимо ли это решение к условиям гонки?


person mark    schedule 15.01.2012    source источник
comment
Это действительно не ответ на вопрос, поскольку он в настоящее время написан. В вашем понимании нет ничего неправильного. У вас есть конкретные проблемы? Если да, можете ли вы опубликовать код?   -  person Sam Miller    schedule 15.01.2012
comment
Я просто хотел подтвердить, что мои предположения/понимание верны, прежде чем идти дальше и реализовывать его. Я думаю, что вы, возможно, сделали это, спасибо. У меня был только ограниченный опыт asio в oast, и я впервые планирую использовать его в гневе.   -  person mark    schedule 15.01.2012
comment
@mark ты написал этот сервер? Я просмотрел несколько примеров многопоточных асинхронных серверов, но для меня это накладные расходы. Не могли бы вы показать свой?   -  person Alex    schedule 28.08.2012


Ответы (1)


Как сказал Сэм Миллер, ваши предположения вполне верны.

Однако я хотел бы указать на проблему, которую вы, возможно, не заметили.

Это правильно, что пряди будут сериализовать async_write(s) и, следовательно, будут потокобезопасными. Но проблема не здесь, async_write сам по себе потокобезопасен, если не используется в том же сокете. И strands тут не помогут, так как не стоит чередовать async_write на одном сокете.

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

person TheSquad    schedule 16.01.2012
comment
Спасибо за ответ. Означает ли это, что цепочка не нужна, если я защищаюсь от вызова async_write для одного и того же сокета из более чем одного потока? - person mark; 17.01.2012
comment
На самом деле здесь следует использовать пряди, но не непосредственно в async_write, а в очереди, которую вы должны реализовать, чтобы не чередовать async_writes. Вы должны найти все свои ответы в одном из моих вопросов stackoverflow.com/questions/7754695/ - person TheSquad; 17.01.2012
comment
Еще раз спасибо - решение Сэма Миллера выглядит очень элегантно - person mark; 17.01.2012
comment
+1 за то, что вы не должны чередовать async_write в одном сокете - person Arnaud; 29.12.2013