2010-06-20 1 views
0

Чтобы не заливать удаленную конечную точку, моему серверному приложению придется реализовать «отправленную» очередь пакетов, которые я хочу отправить.Реализовать успешную очередь «для отправки» с помощью TCP

Я использую Windows Winsock, порты завершения ввода-вывода.

Итак, я знаю, что когда мой код вызывает «socket-> send (.....)», моя пользовательская функция «send()» проверит, действительно ли данные уже «на проводе» (в направлении этот сокет).
Если данные действительно находятся на проводе, они будут просто очереди данных, которые будут отправлены позже.
Если в проводнике нет данных, он вызовет WSASend(), чтобы действительно отправить данные.

До сих пор все хорошо.

Теперь размер данных, которые я собираюсь отправить, непредсказуем, поэтому я разбиваю его на более мелкие куски (скажем, 64 байта), чтобы не тратить память на мелкие пакеты, а очереди или отправлять эти маленькие куски ,

Когда IOCP присваивает статус завершения записи, связанный с переданным мной пакетом, я отправляю следующий пакет в очередь.

В этом проблема; Скорость очень низкая. Я на самом деле получаю, и он находится на локальном соединении (127.0.0.1) со скоростью, равной 200 кб/с.

Итак, я знаю, что мне нужно будет вызвать WSASend() с seveal chunks (массив объектов WSABUF), и это даст гораздо лучшую производительность, но сколько я могу отправить сразу?
Есть ли рекомендуемый размер байтов? Я уверен, что ответ специфичен для моих потребностей, но я также уверен, что есть некоторые «общие» моменты для начала.
Есть ли какой-нибудь другой, лучший способ сделать это?

ответ

1

Конечно, вам нужно только прибегнуть к предоставлению собственной очереди, если вы пытаетесь отправить данные быстрее, чем одноранговое устройство может ее обработать (либо из-за скорости соединения, либо скорости, которую сверст может читать и обрабатывать данные). Тогда вам нужно только прибегнуть к своей собственной очереди данных, если вы хотите контролировать количество используемых системных ресурсов. Если у вас есть только несколько соединений, вполне вероятно, что это все лишнее, если у вас 1000, то это то, о чем вам нужно беспокоиться. Главное, чтобы понять, что, если вы используете ЛЮБОЙ из асинхронных сетевых API-интерфейсов отправки в Windows, управляемых или неуправляемых, то вы передаете контроль за временем жизни ваших буферов отправки в принимающее приложение и сеть. См. here для более подробной информации.

И как только вы решили, что вам нужно беспокоиться об этом, вам не всегда нужно беспокоиться, если сверст может обрабатывать данные быстрее, чем вы можете их производить, тогда нет необходимости замедлять работу в очереди на отправителя. Вы увидите, что вам нужно оцифровать данные, потому что пополнения записи начнут занимать больше времени, поскольку перекрывающиеся записи, которые вы выдаете, не могут завершиться из-за невозможности отправки TCP-стека из-за проблем с управлением потоком (см. http://www.tcpipguide.com/free/t_TCPWindowSizeAdjustmentandFlowControl.htm). На данный момент вы потенциально используете неограниченное количество ограниченных системных ресурсов (как память с невыгружаемым пулом, так и количество страниц памяти, которые могут быть заблокированы, ограничены и (насколько мне известно) оба используются в ожидании записи сокета). ..

В любом случае, этого достаточно ... Предполагаю, что вы уже достигли хорошей пропускной способности, прежде чем добавить свою очередь отправки? Для достижения максимальной производительности вам, вероятно, нужно установить размер окна TCP на нечто большее, чем значение по умолчанию (см. http://msdn.microsoft.com/en-us/library/ms819736.aspx) и опубликовать несколько перекрывающихся записей в соединении.

Предполагая, что у вас уже есть хорошая пропускная способность, вам необходимо разрешить несколько ожидающих перекрывающихся записей до начала очередности, это максимизирует объем данных, которые будут готовы к отправке. После того, как у вас появится волшебное количество незавершенных сообщений, вы можете начать ставить их в очередь, а затем отправить их на основе последующих завершений. Конечно, как только у вас есть ЛЮБЫЕ данные в очереди, все остальные данные должны быть поставлены в очередь. Сделайте число настраиваемым и профильным, чтобы увидеть, что лучше всего работает в качестве компромисса между скоростью и используемыми ресурсами (т. Е. Количеством одновременных подключений, которые вы можете поддерживать).

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

Лично я бы не оптимизировал, используя разброс/сборку записей с несколькими WSABUF до тех пор, пока у вас не будет базы, и вы знаете, что это фактически повышает производительность, я сомневаюсь, что это произойдет, если у вас будет достаточно уже ожидающих данных; но, как всегда, измерьте, и вы узнаете.

64 байта слишком мало.

Возможно, вы уже это видели, но я написал об этом здесь: http://www.lenholgate.com/blog/2008/03/bug-in-timer-queue-code.html, хотя это возможно слишком расплывчато для вас.

+0

Большое спасибо за информацию Len, теперь, после того, как я реализовал этот материал, я действительно могу понять ваши слова. Проблема решена. Это было просто, чем я думал, так как теперь я могу сказать, что все дело в управлении моими буферами, отправке их в сокет и, конечно же, ограничении по мере необходимости. – Poni

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