Where does the mysterious 200 connection come from?
Hey guys, i'm a newbie to async-programming, this is probably a stupid question, but it indeed drove me crazy!!
Here's the code (it just modified a bit from boost.asio's sample):
server.cpp:
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 10000)),limit(0)
{
start_accept();
}
private:
void start_accept()
{
while(1)
{
if(limit <= 10)
{
std::cout << limit << std::endl;
break;
}
}
tcp::socket* socket = new tcp::socket(acceptor_.i开发者_如何学Co_service());
acceptor_.async_accept(*socket,
boost::bind(&tcp_server::handle_accept, this, boost::asio::placeholders::error));
}
void handle_accept(const boost::system::error_code& error)
{
if (!error)
{
++limit ;
start_accept();
}
}
tcp::acceptor acceptor_;
int limit;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
client.cpp:
int main(int argc, char* argv[])
{
int i = 0;
while(1)
{
try
{
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query("127.0.0.1", "10000");
tcp::resolver::iterator endpoint_iterator =resolver.resolve(query);
tcp::endpoint endpoint = *endpoint_iterator;
tcp::socket socket(io_service);
socket.close();
socket.connect(endpoint);
std::cout << i++ << std::endl;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
return 0;
}
I just wanna limit server to accept 10 client. However, client cout the error information after it cout "amazing" 210 (never more or less) continuous numbers. What happend??
I've changed server.cpp a bit. First reconfigured acceptor_ on constructor. Removed while loop, added acceptor_.close();
#include <boost/asio/io_service.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using namespace boost::asio;
using namespace boost::asio::ip;
class tcp_server
{
public:
tcp_server(boost::asio::io_service& io_service)
: acceptor_(io_service),limit(0)
{
tcp::endpoint endpoint(tcp::v4(), 10000);
acceptor_.open(endpoint.protocol());
acceptor_.bind(endpoint);
acceptor_.listen(1); //accept 1 connection at a time
start_accept();
}
private:
void start_accept()
{
tcp::socket* socket = new tcp::socket(acceptor_.io_service());
acceptor_.async_accept(*socket,
boost::bind(
&tcp_server::handle_accept,
this,
socket,
boost::asio::placeholders::error));
}
void handle_accept(tcp::socket* s, const boost::system::error_code& error)
{
if (!error)
{
++limit;
if (limit < 9)
{
start_accept();
}
else
{
acceptor_.close();
}
}
}
tcp::acceptor acceptor_;
int limit;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server(io_service);
io_service.run();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
I suppose, default acceptor can async_accept 200 connection events at a time. You open a socket and close it from the client side in an infinite loop. As a result you open and close a connection 200 times, but it is still 1 connection, 1 socket.
Capping it to 1 by calling listen(1), would force the acceptor to fire an event. You increase the count, then client closes the connection. This way you correctly count each connection event.
Last note: async io uses 1 thread to process connection events, retrieved data etc... Thus, use of mutexes are not necessary.
精彩评论