#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:
Здесь у вас есть две основные проблемы:
- Присоединение к потоку — вы ожидаете завершения потока, прежде чем принять новое соединение
- Использование указателя на сокет, созданный в стеке
Я рекомендую вам это изменить:
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?