I am trying to write a simple server that allows multiple clients to connect. When I run my program, I get the following error as output:
[3730] Press [return] to exit.
Listening on: 127.0.0.1:7777
[5d0] Thread Start
Error: system:995 The I/O operation has been aborted because of either a
thread exit or an application request
I think this is because my Client object is falling out of scope, but I'm not entirely sure if this is actually the problem or if there's something else wrong with my code.
ClientNetwork::ClientNetwork(asio::io_service& ios, const asio::ip::tcp::endpoint& edp) : mIOService(ios), mAcceptor(ios, edp)
{
/*mAcceptor.open(edp.protocol());
mAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(false));*/
listen();
}
ClientNetwork::~ClientNetwork()
{
boost::system::error_code ec;
mAcceptor.close(ec);
mConnectionThreads.join_all();
mClients.clear();
std::cout << "KILLING NETWORK" << std::endl;
}
void ClientNetwork::listen()
{
mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
Client* c = new Client(mIOService);
mAcceptor.listen(boost::asio::socket_base::max_connections);
mAcceptor.async_accept(*c->getSocket(), boost::bind(&ClientNetwork::handleAccept, this, _1, c));
}
void ClientNetwork::handleAccept(const boost::system::error_code& error, Client* client)
{
if (!error)
{
mClients.push_back(client);
mConnectionThreads.create_thread(boost::bind(&ClientNetwork::connectionThread, this));
std::cout << mConnectionThreads.size() << std::endl;
}
else
{
std::cout << "Error: " << error << " " << error.message() << std::endl;
}
}
This is my main (not sure it's entirely helpful but felt it would be good to include:
int main(int argc, char * argv[])
{
boost::shared_ptr< boost::asio::io_service > io_service(
new boost::asio::io_service
);
boost::shared_ptr< boost::asio::io_service::work > work(
new boost::asio::io_service::work(*io_service)
);
boost::shared_ptr< boost::asio::io_service::strand > strand(
new boost::asio::io_service::strand(*io_service)
);
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] Press [return] to exit." << std::endl;
global_stream_lock.unlock();
/*boost::thread_group worker_threads;
for (int x = 0; x < 2; ++x)
{
worker_threads.create_thread(boost::bind(&WorkerThread, io_service));
}*/
/*boost::shared_ptr< boost::asio::ip::tcp::acceptor > acceptor(
new boost::asio::ip::tcp::acceptor(*io_service)
);
boost::shared_ptr< boost::asio::ip::tcp::socket > sock(
new boost::asio::ip::tcp::socket(*io_service)
);*/
try
{
boost::asio::ip::tcp::resolver resolver(*io_service);
boost::asio::ip::tcp::resolver::query query(
"127.0.0.1",
boost::lexical_cast< std::string >(7777)
);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
ClientNetwork clientNet(*io_service, endpoint);
global_stream_lock.lock();
std::cout << "Listening on: " << endpoint << std::endl;
global_stream_lock.unlock();
}
catch (std::exception & ex)
{
global_stream_lock.lock();
std::cout << "[" << boost::this_thread::get_id()
<< "] Exception: " << ex.what() << std::endl;
global_stream_lock.unlock();
}
std::cin.get();
//worker_threads.join_all();
return 0;
}
After creating ClientNetwork
object and when first an asynchronous operation was started you should run io_service::run
method to process handlers in events loop then your program runs until there is at least one asynchronous operation to be executed.
At the end of try
scope put io_service->run()
:
ClientNetwork clientNet(*io_service, endpoint);
global_stream_lock.lock();
std::cout << "Listening on: " << endpoint << std::endl;
global_stream_lock.unlock();
io_service->run();
Without this the destructor of ClientNetwork
class is called and mAcceptor
is closed with printing this error message
void ClientNetwork::handleAccept (...) {
...
std::cout << "Error: " << error << " " << error.message() << std::endl;
}