Информация о контейнере сервера C ++ IOCP

В моей голове было несколько идей о том, как на самом деле содержать большое количество соединений с использованием архитектуры типа ввода-вывода при поддержке KISS. С помощью примеров в Интернете кажется, что большинство используют двойной / единственный связанный список с CONTAINING_RECORD. И, как новичок в IO-серверах (хотя совершенствуюсь каждый день), я тоже использую контейнер связанных списков для IO-архитектуры.

Мой вопрос, вместо того, чтобы использовать один / двойной связанный список для моих соединений, почему я не могу просто создать большой массив и использовать CONTAINING_RECORD? Можно ли использовать вектор STL? Будет ли это работать? Кроме того, каковы другие типы контейнеров, которые лучше всего работают с массивным сервером ввода-вывода.

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

Спасибо за ваше время и ответы.

Изменить: В настоящее время моя архитектура сервера (в двух словах):

Main thread listening and accepting -> Pass over the socket into a container.
Worker threads(2-3) grab IO events for the container of sockets.
Worker threads Read/Write Data on that container.

Основной поток и рабочие потоки используют связанный список. Я хочу уйти от этого.

1

Решение

Ваш «список соединений», вероятно, будет иметь удаления из любой позиции, а не только с конца. За std::vectorудаление элементов в середине — это операция O (N), но для связанных списков это может быть O (1). (Для односвязных списков это не тривиально и может потребовать неудобного API).

std::map может быть интересным выбором, поскольку он предлагает как O(log N) поиск и удаление элементов.

1

Другие решения

Как и во всех структурах данных, это очень сильно зависит от того, что вы хотите с ним делать.

В предыдущей работе я проводил большую часть своего времени, работая на чрезвычайно многопоточном сервере C ++, который в своем воплощении Windows использовал порты завершения ввода-вывода (в бэкэнде Solaris использовался / dev / poll, который не так уж отличается по нескольким элементам). Этот хранит связанные с соединением структуры данных в map-подобная структура, датируемая до STL, с использованием файловых дескрипторов в качестве значений ключей. Таким образом, всякий раз, когда мы получаем событие в соединении, мы можем искать связанные с ним структуры данных по дескриптору, который нам передал уровень ввода-вывода. Новые соединения были просты в обращении — просто добавьте запись в словарь — и закрытые соединения также можно очистить довольно тривиально.

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

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

0

По вопросам рекламы [email protected]