WSARecv, Completionport Model, как управлять буфером и избежать переполнения? - PullRequest
1 голос
/ 17 февраля 2012

Моя проблема: мой сервер Completionport будет получать данные неизвестного размера от разных клиентов, дело в том, что я не знаю, как избежать переполнения буфера / как избежать «переполнения» моего (принимающего) буфера данными.

Теперь к заданию: 1) Если я сделаю вызов приема через WSARecv, будет ли рабочий поток работать как функция обратного вызова?Я имею в виду, выкапывает ли он приемный вызов только после его завершения или же он выкапывает его, когда происходит прием?Содержит ли переменная lpNumberOfBytes (из GetQueuedCompletionStatus) количество полученных до сих пор байтов или общее число полученных байтов?

2) Как избежать переполнений, я подумал о динамически распределенных структурах буфера, но опять же, какузнать, насколько большим будет пакет?

edit: я не хочу спрашивать об этом, но есть ли какой-нибудь "простой" метод для управления буфером и предотвращения переполнения?Синхронизация звучит для меня безгранично, по крайней мере, сейчас

Ответы [ 2 ]

1 голос
/ 17 февраля 2012

Если я сделаю вызов приема через WSARecv, рабочий поток работает как функция обратного вызова?

См. Сообщение @valdo.Данные завершения поставлены в очередь в ваш пул потоков, и один из них будет подготовлен для их обработки.

'Я имею в виду, выкапывает ли получаемый вызов только после завершения?'Да - отсюда и название.Обратите внимание, что значение «завершено» может отличаться.в зависимости от протокола.В случае TCP это означает, что некоторые одноранговые байты данных были получены от однорангового узла.

'Содержит ли переменная lpNumberOfBytes (из GetQueuedCompletionStatus) количество полученных до сих пор байтов или общее количество полученных байтов?'Он содержит количество байтов, полученных и загруженных в буферный массив, предоставленный только в этом завершении IOCP.

«Как избежать переполнения, я подумал о динамически распределенных структурах буфера, но опять же, как мне узнать, насколько большим будет пакет?»Вы не можете получить переполнение, если вы предоставите буферные массивы - потоки ядра, которые загружают буфер, не будут превышать переданную длину буфера.На уровне приложений, учитывая потоковую природу TCP, вам решать, как обрабатывать буферные массивы в пригодные для использования блоки протокола уровня приложения.Используя свои знания о предоставляемых услугах, вы должны принять решение о подходящей схеме управления буфером.

Последний сервер IOCP был, как правило, универсальным.Я использовал массив буферных пулов и пул объектов «буфер-носитель», выделяемых при запуске (вместе с пулом объектов сокетов).Каждый пул буферов содержал буферы разного размера.После нового соединения я выпустил WSARecv, используя один буфер из наименьшего пула.Если этот буфер был полностью заполнен, я использовал буфер из следующего по величине пула для следующего WSARecv и т. Д.

Затем возникает проблема с порядковыми номерами, необходимыми для предотвращения неправильной буферизации с несколькимиобработчик потоков: (

1 голос
/ 17 февраля 2012

_1.Порт завершения является своего рода очередью (со сложной логикой относительно приоритета потоков, ожидающих завершения из него завершения ввода-вывода).Всякий раз, когда ввод / вывод завершается (успешно или нет), он ставится в очередь в порт завершения.Затем он удаляется одним из потоков с именем GetQueuedCompletionStatus.

, так что вы никогда не блокируете ввод / вывод "в процессе".Более того, он обрабатывается вашим рабочим потоком асинхронно.То есть он задерживается до тех пор, пока ваш поток не вызовет GetQueuedCompletionStatus.

_2.Это на самом деле сложный вопрос.Синхронизация не является простой задачей в целом, особенно когда речь идет о симметричной многопоточности (когда у вас есть несколько потоков, каждый может делать все).

Один из параметров, которые вы получаете с завершенным вводом / выводом, этоуказатель на структуру OVERLAPPED (которую вы указали для функции, которая выдавала ввод-вывод, например WSARecv).Распространенной практикой является выделение вашей собственной структуры, основанной на OVERLAPPED (либо она наследуется, либо имеет первый член).Получив завершение, вы можете привести исключенную OVERLAPPED к вашей фактической структуре данных.Там у вас может быть все необходимое для синхронизации: синхронизация объектов, описание состояния и т. Д.

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

...