I've implemented a SocketServer using boost. This SocketServer is intended to work as follow:
Here is my code:
ServerSocket::ServerSocket(unsigned int port)
{
_io_service.reset(new boost::asio::io_service()) ;
_endpoint.reset(new boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
_acceptor.reset(new boost::asio::ip::tcp::acceptor(*_io_service, *_endpoint)) ;
_newConnection = false;
}
bool ServerSocket::accept(boost::asio::ip::tcp::socket& socket, int timeout)
{
_newConnection = false;
_acceptor->async_accept(socket, boost::bind(&ServerSocket::handleAccept, this, &socket));
_io_service->reset();
if (timeout > 0)
{
int incrementation = 1;
int time_spent = 0;
while (time_spent < timeout && !_io_service->poll_one())
{
time_spent += incrementation;
sleep(incrementation);
}
}
else
{
_io_service->run_one();
}
if (!_newConnection)
{
_acceptor->cancel();
}
return _newConnection;
}
void ServerSocket::handleAccept(boost::asio::ip::tcp::socket* pSocket)
{
_newConnection = true;
};
My problem is the following: when I call accept() with a timeout and a socket A. If the timeout is reached and I call it again with a new socket B, if then the accept() works, I handle A instead of B.
Tell me if there are information missing.
You can simply use the io_service's task loop, and use a deadline timer to cancel the operation on the acceptor.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
using namespace boost;
using asio::ip::tcp;
struct ServerSocket
{
asio::io_service _io_service;
tcp::endpoint _endpoint;
tcp::acceptor _acceptor;
asio::deadline_timer _timer;
bool _newConnection;
ServerSocket(unsigned int port)
: _io_service(),
_endpoint(tcp::v4(), port),
_acceptor(_io_service, _endpoint),
_timer(_io_service),
_newConnection(false)
{
}
void timer_expired(boost::system::error_code ec)
{
if (!ec)
{
_acceptor.cancel();
}
}
bool accept(boost::asio::ip::tcp::socket& socket, int timeout)
{
_newConnection = false;
_io_service.reset();
_timer.expires_from_now(boost::posix_time::seconds(timeout));
_timer.async_wait(boost::bind(&ServerSocket::timer_expired, this, asio::placeholders::error));
_acceptor.async_accept(socket, boost::bind(&ServerSocket::handleAccept, this, &socket, asio::placeholders::error));
_io_service.run();
return _newConnection;
}
void handleAccept(boost::asio::ip::tcp::socket* pSocket, boost::system::error_code ec)
{
if (!ec)
{
_timer.cancel();
_newConnection = true;
}
};
};
int main()
{
ServerSocket s(6767);
tcp::socket socket(s._io_service);
if (s.accept(socket, 3))
std::cout << "Accepted connection from " << socket.remote_endpoint() << "\n";
else
std::cout << "Timeout expired\n";
}
You should probably explicitly check the operation_canceled error code instead if just doing !ec
but I'll leave that as an exercise for the reader.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.