I tried to start with the boost asio chat example and derive an own networking program. Unfortunately I have some problem understanding what really happens. I tried to reduce my program to an absolute minimum. A server class waits for incoming connections and creates a session object to handle the connection. This is the code of the server:
#include <cstdint>
#include <iostream>
#include <sstream>
#include <memory>
#include <vector>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
class Session : public std::enable_shared_from_this<Session>
{
public:
Session(boost::asio::ip::tcp::socket __oSocket);
virtual ~Session();
void StartSession();
private:
void StartRecv();
std::vector<int32_t> m_vecSetupReceiveBuffer;
boost::asio::ip::tcp::socket m_oSocket;
};
Session::Session(boost::asio::ip::tcp::socket __oSocket) :
m_vecSetupReceiveBuffer({2}),
m_oSocket(std::move(__oSocket))
{ }
Session::~Session()
{
std::cout << "Deleted session" << std::endl;
}
void Session::StartSession()
{
auto self(shared_from_this());
std::cout << "StartSession()" << std::endl;
boost::asio::async_write(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
[this, self](boost::system::error_code _oError, std::size_t)
{
std::cout << m_vecSetupReceiveBuffer.size() << std::endl;
StartRecv();
});
}
void Session::StartRecv()
{
auto self(shared_from_this());
std::cout << "StartRecv()" << std::endl;
boost::asio::async_read(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
[this, self](boost::system::error_code _oError, std::size_t)
{});
}
class Server
{
public:
Server(boost::asio::io_service& _rIOService, uint32_t _nPort);
virtual ~Server();
private:
void StartAccept();
boost::asio::ip::tcp::acceptor m_oAcceptor;
boost::asio::ip::tcp::socket m_oSocket;
};
Server::Server(boost::asio::io_service& _rIOService, uint32_t _nPort) :
m_oAcceptor(_rIOService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), _nPort)),
m_oSocket(_rIOService)
{
StartAccept();
}
Server::~Server()
{}
void Server::StartAccept()
{
m_oAcceptor.async_accept(m_oSocket,
[this](boost::system::error_code _oError)
{
std::make_shared<Session>(std::move(m_oSocket))->StartSession();
StartAccept();
});
}
int main(int argc, char* argv[])
{
boost::asio::io_service _oIOServerService;
std::shared_ptr<Server> _pServer(std::make_shared<Server>(_oIOServerService, 2000));
_oIOServerService.run();
return 0;
}
This code runs as intended, but as I tried to adjust some things and to play a little bit around I figured out that I don't understand when shared pointers are really created and deleted and where they are stored. For example I tried to change the std::make_shared<Session>(std::move(m_oSocket))->StartSession();
to std::make_shared<Session>(std::move(m_oSocket));
and added the StartSession();
in the constructor of the Session class. If I run the code then, it throws
terminate called after throwing an instance of 'std::bad_weak_ptr'
what(): bad_weak_ptr
Aborted (core dumped)
This presumably happens in auto self(shared_from_this());
. But I don't understand why? What should I change in my code? So I think my problem is that I don't understand how to use the shared_ptr correctly, how to use it in these constructions, where I can access it and how to make it accessible. Further it is not clear why I sometimes have to user this
and when to use shared_from_this()
. Is there a good tutorial, or a simple rule of thumb?
It is also unclear to me, why some user the lambda function notation, and some the boost::bind
notation and what are the differences?
So please forgive my newbie questions, I tried to find some information in tutorials but am only confused with these shared pointers and boost::asio. It seems always to do strange things.