повысьте asio:ведение списка подключенных клиентов

StackOverflow https://stackoverflow.com/questions/1664502

  •  12-09-2019
  •  | 
  •  

Вопрос

Я ищу лучший способ изменить Boost Asio Пример HTTP-сервера 3 вести список подключенных в данный момент клиентов.

Если я изменю server.hpp из примера как:

class server : private boost::noncopyable
{
public:
    typedef std::vector< connection_ptr > ConnectionList;

    // ...

    ConnectionList::const_iterator GetClientList() const
    {
        return connection_list_.begin();
    };

    void handle_accept(const boost::system::error_code& e)
    {
        if (!e)
        {
            connection_list_.push_back( new_connection_ );
            new_connection_->start();
            // ...
        }
    }

private:
    ConnectionList connection_list_;
};

Затем я увеличиваю время жизни объекта connection таким образом, чтобы он не выходил за пределы области видимости и не отключался от клиента, потому что у него все еще есть ссылка, поддерживаемая в ConnectionList.

Если вместо этого мой список подключений определен как typedef std::vector< boost::weak_ptr< connection > > ConnectionList; тогда я рискую, что клиент отключится и обнулит свой указатель, пока кто-то использует его из GetClientList().

У кого-нибудь есть предложения о хорошем и безопасном способе сделать это?

Спасибо, Пауль

Это было полезно?

Решение

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

Типичным методом обработки этого является использование довольно простого тайм-аута - клиент считается "подключенным" в течение некоторого произвольного промежутка времени (несколько минут) после отправки запроса.Какой-либо файл cookie используется для идентификации клиента, отправляющего конкретный запрос.

Остальная часть того, о чем вы говорите, - это просто вопрос обеспечения потокобезопасности коллекции, которую вы используете для хранения информации о соединении.У вас есть один поток, который добавляет соединения, один поток, который их удаляет, и N потоков, которые используют данные, находящиеся в данный момент в списке.Стандартные коллекции не гарантируют никакой потокобезопасности, но есть другие, которые это делают.

Другие советы

Извините, у меня недостаточно репутации, чтобы комментировать, поэтому я напишу это здесь.

Прокомментируйте ответ:"HTTP не имеет состояния" - но соединение выполнено по состоянию!Пожалуйста, внимательно прочитайте HTTP / 1.1 docs, поведение по умолчанию - "Подключение:keep-alive", поэтому, если вы реализуете HTTP-сервер, вы должны дождаться другого запроса по тому же соединению.Это особенно важно для HTTPS, экономит много времени за счет сокращения количества рукопожатий.Вот почему каждый соответствующий сервер должен понимать, как поддерживать соединения.

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

Напишите функцию в вашем классе "connection", например tell_server_im_done , в этой функции сообщите вашему экземпляру "server", чтобы он удалил себя из списка.Вы должны предоставить вашему конструктору "connection" указатель или ссылку на ваш серверный объект, чтобы это сработало.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top