IOCP с WSASend и OVERLAPPED пулом

Это сервер с сокетами, использующими IOCP. Я инициализирую пул OVERLAPPED, который использую для отправки вызовов WSASend (). Каждый вызов WSASend () извлекает один указатель OVERLAPPED из пула и возвращает его в рабочий поток IOCP при уведомлении.

Однако, когда клиент отключается, НЕКОТОРЫЕ из ожидающих вызовов WSASend () сбрасывается, и поэтому у меня нет возможности повторно использовать указатели OVERLAPPED, которые были взяты из пула.

Как я могу на 100% отменить все ожидающие вызовы WSASend (), убедившись, что они не попадут к работнику IOCP, чтобы я мог вручную повторно использовать указатели OVERLAPPED при отключении?

Спасибо.


person user1588293    schedule 24.05.2013    source источник
comment
Вы хотите сказать, что обратный вызов IOCP не вызывается с кодом ошибки, если клиент отключается во время выполнения перекрывающейся отправки?   -  person Remy Lebeau    schedule 24.05.2013
comment
Закрытие сокета должно прервать выполнение любой отправки / получения. Вы закрываете сокет, когда обнаруживаете разъединение? В худшем случае вы можете просто обернуть свою OVERLAPPED структуру (вам действительно следует использовать WSAOVERLAPPED, BTW) в struct, который также содержит исходный SOCKET, таким образом, когда происходит отключение, вы можете прокручивать свои элементы, которые находятся в процессе поиска отключенных SOCKET и тогда вы узнаете, какие предметы можно переработать.   -  person Remy Lebeau    schedule 24.05.2013
comment
Да, в любом случае, он унаследован, я хочу быть уверенным, что при вызове closesocket (s) все ожидающие вызовы WSASend () не будут отправлены в IOCP. Если я могу в этом убедиться, я могу переработать все указатели OVERLAPPED вручную, не беспокоясь об их повторной переработке дважды.   -  person user1588293    schedule 24.05.2013
comment
Между моментом отключения клиента и моментом, когда вы закрываете этот сокет, разрешаете ли вы потоку перейти в состояние предупреждения, чтобы можно было вызвать обратный вызов IOCP? В противном случае, если вы воспользуетесь подходом struct, вы можете добавить к нему bool, чтобы отметить, когда он находится в пуле, затем вы можете проверить это значение при принятии решения о переработке или нет.   -  person Remy Lebeau    schedule 24.05.2013
comment
Да, я мог бы это сделать, но как я могу узнать, что после вызова closesocket () и повторного использования всех сохраненных структур, как я могу узнать, что IOCP не получит эти уведомления о копировании WSASend ()? Для меня это звучит как состояние гонки, и я должен убедиться, что они не дойдут до рабочего IOCP на 100000%. Как я могу в этом убедиться?   -  person user1588293    schedule 24.05.2013
comment
Структуры будут помечены, чтобы IOCP мог проверить это на случай, если он действительно будет вызван после повторного использования. И это не гонка, поскольку вы контролируете, когда поток (-ы) IOCP входят в состояние предупреждения, поэтому могут быть вызваны обратные вызовы IOCP, поэтому просто не переходите в состояние предупреждения при повторном использовании структур закрытого сокета. Теперь, если допустить, все это зависит от предположения, что обратные вызовы IOCP не вызываются при отключении, что я думаю, что они должны быть, и вы еще не оспаривали.   -  person Remy Lebeau    schedule 25.05.2013
comment
Теоретически это не гарантирует, что снова ожидающие вызовы WSASend () действительно будут опубликованы после отключения и повторного использования.   -  person user1588293    schedule 25.05.2013
comment
Да, установка флага в структуры, чтобы не повторно использовать их дважды, может помочь, но что, если в середине этих двух ситуаций вызовется другой вызов WSASend (), который возьмет эту конкретную структуру, которую я только что переработал из пула, и сразу после этого вызов WSASend () из отключенного get обрабатывается IOCP worker и повторно используется, флаг был сброшен новым вызовом WSASend () ... это то, что я имел в виду под состоянием гонки.   -  person user1588293    schedule 25.05.2013
comment
Нет никакого способа предотвратить это, если Windows API не предоставит способ отменить ВСЕ ОЖИДАЮЩИЕСЯ вводы-вывода сокета и быть на 100% уверенным, что они не будут отправлены в IOCP позже, тогда переработка структур будет легкой и больше не о чем беспокоиться .   -  person user1588293    schedule 25.05.2013
comment
Вы уже пробовали CancelIo/Ex()?   -  person Remy Lebeau    schedule 25.05.2013


Ответы (1)


Это не то, как работают IOCP.

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

Вам нужно подождать, пока это произойдет, и как только это произойдет, вы можете отключиться.

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

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

Чтобы помочь в чистом завершении работы, у меня есть счетчик, который я могу ждать, который отслеживает количество «активных» объектов (сокетов) для каждого соединения.

Чтобы завершить работу, вы прерываете все соединения, а затем ждете, пока счетчик соединений не достигнет нуля. В этот момент все ваши объекты либо уничтожены, либо находятся в ваших бассейнах, и вы можете очистить их.

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

person Len Holgate    schedule 15.08.2013
comment
Счетчик ссылок - это структура OVERLAPPED, я имею в виду, каждая структура OVERLAPPED должна иметь свою собственную, и она должна быть атомарной, поскольку IOCP работает с несколькими потоками, верно? Меня беспокоило то, что слишком большое увеличение / уменьшение многих атомарных счетчиков могло повлиять на производительность и масштабируемость потоков. Может ли это случиться, или это беспочвенное беспокойство? - person Marco Pagliaricci; 19.12.2013
comment
Это может сработать, а может быть и хуже на оборудовании NUMA; как всегда профилируйте и посмотрите. В настоящий момент я корректирую свою структуру, чтобы мы не использовали счетчик ссылок во время фактической отправки IOCP (т.е. при обычных операциях нет необходимости в счетчике ссылок столько, сколько мы использовали). Я все еще сохраняю его, поскольку он обеспечивает эффективный дизайн сервера, когда вы хотите хранить буферы дольше, чем просто одна операция IOCP, но для более простых серверов (чтение, анализ сообщения, запись ответа по входящему сообщению, ответ) нет реф манипуляций вообще больше нет. - person Len Holgate; 19.12.2013