I have software that I would like to make a TCP client. I don't know if this is the best architecture, but in my software I create a stream that will be used for network I / O. If there is a better architecture, I would appreciate some recommendations and advice.
Both threads have a reference to the boost :: asio :: io_service object and a Session object that encapsulates the socket object. The sesson object looks something like this:
class Session
{
public:
Session(
boost::asio::io_service & io_service,
std::string const & ip_address,
std::string const & port)
: io_service_(io_service),
resolver_(io_service),
socket_(io_service),
ip_address_(ip_address),
port_(port),
{}
virtual void start();
virtual ~Session();
virtual void stop();
void write(std::string const & msg);
void handle_resolve(
const boost::system::error_code & error,
boost::asio::ip::tcp::resolver::iterator endpoint_itr);
void handle_connect(
const boost::system::error_code & error,
boost::asio::ip::tcp::resolver::iterator endpoint_itr);
void handle_close();
void handle_write(const boost::system::error_code & error);
private:
boost::asio::io_service & io_service_;
boost::asio::ip::tcp::resolver resolver_;
boost::asio::ip::tcp::socket socket_;
std::string ip_address_;
std::string port_;
};
In the I / O loop thread, the start () method of the session object is called, which connects to the server. (This works, by the way). The thread is then in a loop that calls the run () method in the I / O service object [io_service_.run ()] to fire events.
write() , , boost:: async_write , , ( handle_write).
-, , handle_write. , async_write() . . tcpdump.
, ? ? , I/O.
, io ( ):
boost::asio::io_service io_service;
boost::shared_ptr<Session> session_ptr;
boost::thread io_thread;
....
session_ptr.reset(
new Session::Session(
io_service,
std::string("127.0.0.1"),
std::string("17001")));
io_thread = boost::thread(
boost::bind(
&Session::start,
session_ptr_.get()));
start() :
void Session::start()
{
typedef boost::asio::ip::tcp tcp;
tcp::resolver::query query(
tcp::v4(),
ip_address_,
port_);
resolver_.async_resolve(
query,
boost::bind(
&Session::handle_resolve,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
while(1){
io_service_.run();
}
}
:
void Session::handle_resolve(
const boost::system::error_code & error,
boost::asio::ip::tcp::resolver::iterator endpoint_itr)
{
if (!error)
{
boost::asio::ip::tcp::endpoint endpoint = *endpoint_itr;
socket_.async_connect(
endpoint,
boost::bind(
&Session::handle_connect,
this,
boost::asio::placeholders::error,
++endpoint_itr));
}
else
{
std::cerr << "Failed to resolve\n";
std::cerr << "Error: " << error.message() << std::endl;
}
}
:
void Session::handle_connect(
const boost::system::error_code & error,
boost::asio::ip::tcp::resolver::iterator endpoint_itr)
{
typedef boost::asio::ip::tcp tcp;
if (!error)
{
std::cerr << "Connected to the server!\n";
}
else if (endpoint_itr != tcp::resolver::iterator())
{
socket_.close();
socket_.async_connect(
*endpoint_itr,
boost::bind(
&Session::handle_connect,
this,
boost::asio::placeholders::error,
++endpoint_itr));
}
else
{
std::cerr << "Failed to connect\n";
}
}
write(), .
void Session::write(
std::string const & msg)
{
std::cout << "Write: " << msg << std::endl;
boost::asio::async_write(
socket_,
boost::asio::buffer(
msg.c_str(),
msg.length()),
boost::bind(
&Session::handle_write,
this,
boost::asio::placeholders::error));
}
, , :
void Session::handle_write(
const boost::system::error_code & error)
{
if (error)
{
std::cout << "Write complete with errors !!!\n";
}
else
{
std::cout << "Write complete with no errors\n";
}
}