问题
I´m trying to build an asynchronous server using boost::asio
.
The server is read only and needs to have a session timeout: If a session passes more than N seconds without receiving data, the session is disconnected and the client needs to start the connection again.
SocketServer.hpp
class SocketServer {
public:
SocketServer(boost::asio::io_service& service);
virtual ~SocketServer();
void StartAsync(int port);
void StopAsync();
private:
void StartAccept();
void HandleAccept(std::shared_ptr<SocketSession> session, const boost::system::error_code& errorCode);
boost::asio::io_service &ioService;
boost::asio::ip::tcp::acceptor acceptor;
};
SocketServer.cpp
SocketServer::SocketServer(boost::asio::io_service& service) :
ioService(service),
acceptor(service) {}
SocketServer::~SocketServer() {}
void SocketServer::StartAsync(int port)
{
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), port);
acceptor.open(ep.protocol());
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor.bind(ep);
StartAccept();
}
void SocketServer::StopAsync()
{
acceptor.cancel();
}
void SocketServer::StartAccept()
{
std::shared_ptr<SocketSession> session = std::shared_ptr<SocketSession>(new SocketSession(ioService));
acceptor.listen();
acceptor.async_accept(session->getSessionSocket(), boost::bind(&SocketServer::HandleAccept, this, session, boost::asio::placeholders::error));
}
void SocketServer::HandleAccept(std::shared_ptr<SocketSession> session, const boost::system::error_code& errorCode)
{
std::stringstream ss;
if (errorCode)
{
std::cout << "Error accepting incoming connection: Error: " << boost::system::system_error(errorCode).what();
}
else
{
ss << "Connection accepted from address " << socket.remote_endpoint().address().to_string() << ".";
session->start();
}
StartAccept();
}
SocketSession.hpp
#define MAX_BUFFER_LENGTH 1024
class SocketSession {
public:
SocketSession(boost::asio::io_service& service);
virtual ~SocketSession();
void start();
void startTimeoutHandler();
void HandleRead(size_t bytesTransferred, const boost::system::error_code& errorCode);
boost::asio::ip::tcp::socket& getSessionSocket();
private:
boost::asio::ip::tcp::socket sessionSocket;
char readBuffer[MAX_BUFFER_LENGTH];
boost::asio::deadline_timer readTimeout;
void TimeoutHandler(const boost::system::error_code& errorCode);
};
SocketSession.cpp
SocketSession::SocketSession(boost::asio::io_service& service) :
sessionSocket(service),
readTimeout(service) {}
SocketSession::~SocketSession() {}
void SocketSession::start()
{
startTimeoutHandler();
sessionSocket.async_read_some(boost::asio::buffer(readBuffer, MAX_BUFFER_LENGTH), boost::bind(&SocketSession::HandleRead, this, boost::asio::placeholders::bytes_transferred, boost::asio::placeholders::error));
}
void SocketSession::startTimeoutHandler()
{
readTimeout.expires_from_now(boost::posix_time::seconds(10));
readTimeout.async_wait(boost::bind(&SocketSession::TimeoutHandler, this, boost::asio::placeholders::error));
}
void SocketSession::HandleRead(size_t bytesTransferred, const boost::system::error_code& errorCode)
{
std::stringstream ss;
readTimeout.expires_from_now(boost::posix_time::seconds(10));
if (errorCode)
{
std::cout << "Error reading data for session: Error: " << boost::system::system_error(errorCode).what();
delete this;
}
else
{
std::string data(readBuffer, bytesTransferred);
std::cout << "Data read:" << data << std::endl;
}
start();
}
{
return sessionSocket;
}
void SocketSession::TimeoutHandler(const boost::system::error_code& errorCode)
{
delete this;
}
This compiles fine,
My problem here is the session returns the following error once it is loaded:
Error: Operation canceled
at the SocketSession::HandleRead
.
It seens that boost::bind doesn´t like my std::shared_ptr
. I tried a version changing it to normal pointers and the server works fine.
So, here goes my questions:
Is it possible to work on boost::bind
with std::shared_ptr
?
If yes, am I doing that in the correct way ?
What may be causing my code to exit without listening to the client ?
来源:https://stackoverflow.com/questions/34019004/c-boostbind-with-stdshared-ptr-trowing-operation-canceled-on-timeout-handl