Как справиться с высокочастотными данными? - PullRequest
3 голосов
/ 28 февраля 2009

У меня есть приложение C ++, которое получает данные о запасах и пересылает в другое приложение через сокет (действующий как сервер).

На самом деле функция WSASend через несколько секунд возвращает код ошибки 10055, и я обнаружил, что это сообщение об ошибке

«Недоступно буферного пространства. Не удалось выполнить операцию с сокетом, поскольку в системе не было достаточно буферного пространства или из-за переполнения очереди».

Проблема возникает только тогда, когда я запускаю приложение в нерабочее время рынка, поскольку мы получаем данные за целый день (приблизительно 130 МБ) за несколько минут (я полагаю, это относительно много) Я делаю это в качестве теста на устойчивость.

Я попытался увеличить буфер отправки SO_SNDBUF, используя функцию setsockopt, но та же проблема все еще существует. Как я могу решить эту проблему? это связано с буфером получателя?

Сведения об отправке:

Для каждого полного сообщения я вызываю метод send, который использует перекрывающиеся сокеты

EDIT: Может кто-нибудь дать общие рекомендации по обработке высокочастотных данных в C ++?

Ответы [ 2 ]

6 голосов
/ 28 февраля 2009

Управление потоком TCP приведет к заполнению внутреннего буфера отправки, если получатель недостаточно быстро обрабатывает свой конец сокета. Из сообщения об ошибке может показаться, что вы отправляете данные без учета того, как быстро стек Winsock может их обработать. Было бы полезно, если бы вы могли указать, как именно вы отправляете данные? Вы ожидаете получения всех данных, а затем отправляете один большой блок или поштучно?

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

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

0 голосов
/ 10 марта 2009

ответ Ника в значительной степени ударяет гвоздь по голове; вы, скорее всего, исчерпали «лимит заблокированных страниц», запустив слишком много перекрывающихся отправок одновременно. В идеале вам нужно буферизовать ваши данные в ваших собственных буферах памяти и иметь только установленное количество отложенных пересылок, ожидающих в любой момент времени. Я говорю о том, как моя инфраструктура IOCP позволяет вам справляться с подобной ситуацией здесь http://www.lenholgate.com/blog/2008/07/write-completion-flow-control.html и с проблемами управления потоком окна получения TCP здесь http://www.lenholgate.com/blog/2008/06/data-distribution-servers.html и здесь http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html.

Мое предпочтительное решение состоит в том, чтобы разрешить настраиваемое количество ожидающих перекрывающихся отправок в любое время, и как только этот предел будет превышен, чтобы начать буферизацию данных, а затем использовать завершение ожидающих перекрывающихся отправок для управления отправкой буферизованных данных. Это позволяет строго контролировать количество невыгружаемого пула и количество используемых «заблокированных страниц», а также позволяет отправлять множество соединений с максимально быстрой скоростью, но при этом контролировать ресурсы, которые они используют.

...