При использовании IOCP у вас есть два элемента пользовательских данных, которые вы можете использовать для каждой асинхронной операции.
Первый - это ключ завершения, который является данными "для каждого соединения" и устанавливается, когда вы связываете дескриптор файла или сокет с портом завершения, вызывая CreateIoCompletionPort() с дескриптором сокета/файла и существующим портом завершения. Это значение возвращается при каждом вызове GetQueuedCompletionStatus() для данного соединения.
Вторая - это «расширенная перекрывающаяся» структура, которая представляет собой данные «за операцию». Для каждой параллельной операции ДОЛЖНА быть назначена уникальная перекрывающаяся структура.
В приведенном выше дизайне вы должны использовать данные «на соединение» для идентификации вашего соединения. У вас есть два связанных соединения (сокета), поэтому у меня было бы два связанных класса, по одному для каждой стороны соединения. Класс (или структура, если вы используете C, а не C++) будет содержать сокет, указатель на другую половину соединения и флаг, указывающий, какой это тип соединения. При использовании C++ эти два класса будут производными от общего базового класса, чтобы можно было вызвать функцию-член, чтобы определить, какой тип соединения представляет ключ завершения. Если вы используете C, используйте размеченный союз.
Затем вы просто приводите свой ключ завершения к базе, затем определяете, какой тип соединения у вас есть, и приводите к правильному классу/структуре. Теперь вы знаете, на каком соединении выполнялась операция. Класс подключения может хранить все состояние конечного автомата, который запускает его протокол.
Как упоминает Криаг, каждая перекрывающаяся структура «уникальна для каждой операции», и в моем коде IOCP это, как правило, разрешает доступ к буферу данных для операции и флагу, который сообщает мне, что это была за операция (чтение/запись/принятие/подключение и т. д.). ).
Одна потенциальная сложность заключается в сохранении данных для каждой операции и для каждого соединения до тех пор, пока не будут завершены все незавершенные операции, которые их используют. Я лично предпочитаю подсчет ссылок как для каждого соединения, так и для данных операции, но я уверен, что есть и другие способы.
У меня есть пример кода для IOCP, который использует эти концепции (хотя и не предоставляет пример «двух соединений»), вы можете скачать его здесь: http://www.serverframework.com/products---the-free-framework.html
person
Len Holgate
schedule
05.09.2012