C asio обеспечивает асинхронное выполнение потока

#c #multithreading #boost-asio

#c #многопоточность #boost-asio

Вопрос:

Я получил простое серверное приложение. При подключении нового клиента он обрабатывает запрос от клиента и отправляет ему данные обратно. Моя проблема заключается в обеспечении асинхронного выполнения потока обработки. Теперь, когда начался поток обработки, он останавливает цикл приема и ожидает возврата соответствующей функции. Вопрос в том, как организовать продолжение цикла приема (чтобы иметь возможность одновременно обрабатывать другое соединение) после запуска потока обработки?

Server.h:

 class Server
{
private:
    //Storage
    boost::asio::io_service service;
    boost::asio::ip::tcp::acceptor* acceptor; 
    boost::mutex mtx;

    //Methods
    void acceptorLoop();
    void HandleRequest(boost::asio::ip::tcp::socket* clientSock);

public:
    Server();
};
 

Server.cpp

 void Server::acceptorLoop()
{
    std::cout << "Waiting for clients..." << std::endl;

    while (TRUE)
    {
        boost::asio::ip::tcp::socket clientSock (service);
        acceptor->accept(clientSock); //new socket accepted
        std::cout << "New client joined! ";
        boost::thread request_thread (amp;Server::HandleRequest, this, amp;clientSock); //create a thread
        request_thread.join(); //here I start thread, but I want to continue acceptor loop and not wait until function return.
    }
}

void Server::HandleRequest(boost::asio::ip::tcp::socket* clientSock)
{
    if (clientSock->available())
    {
        //Works with socket
    }
}

Server::Server()
{
    acceptor = new boost::asio::ip::tcp::acceptor(service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 8001));
    acceptorLoop(); //loop started
}
 

Комментарии:

1. Сохраните поток, например, в виде вектора, и не присоединяйтесь сразу после создания потока. Кроме того, тогда вам нужно использовать какой-то другой способ обработки clientSock объекта, потому что прямо сейчас вы передаете указатель на объект, который выйдет из области видимости (и будет уничтожен) после завершения цикла.

Ответ №1:

Здесь у вас есть две основные проблемы:

  1. Присоединение к потоку — вы ожидаете завершения потока, прежде чем принять новое соединение
  2. Использование указателя на сокет, созданный в стеке

Я рекомендую вам это изменить:

     boost::asio::ip::tcp::socket clientSock (service);
    acceptor->accept(clientSock); //new socket accepted
    std::cout << "New client joined! ";
    std::thread{std::bind(amp;Server::HandleRequest, this, std::placeholders::_1), std::move(clientSock)}.detach();
 

И handleRequest изменится на это:

 void Server::HandleRequest(boost::asio::ip::tcp::socketamp;amp; clientSock)
{
    if (clientSock.available())
    {
        //Works with socket
    }
}
 

Вы также можете сохранить поток где-нибудь и присоединиться к нему позже вместо отсоединения.

Ответ №2:

Итак, почему вы вызываете join? Join — это ожидание завершения потока, а вы говорите, что не хотите ждать поток, так что, хорошо… просто не вызывать join?