I would like to have a TCP server receiving data in one thread and being able to send data from another one.
My code does echo what the server receives, so it's possible to write from the same thread but fails to send messages from the main.
I believe it has something to do with the socket not accessible but I need a push to get back on track, thanks!
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class session
: public std::enable_shared_from_this<session>
{
public:
session(tcp::socket socket)
: socket_(std::move(socket))
{
}
void start()
{
do_read();
}
void write(char *msg, std::size_t length)
{
do_write(msg, length);
}
private:
void do_read()
{
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_write(data_, length);
}
});
}
void do_write(char *msg, std::size_t length)
{
auto self(shared_from_this());
boost::asio::async_write(socket_, boost::asio::buffer(msg, length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_read();
}
else
{
std::cout << ec.message() << std::endl;
std::cout << socket_.is_open() << std::endl;
}
});
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(boost::asio::io_service& io_service, short port)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
socket_(io_service)
{
do_accept();
}
void send(char *msg, std::size_t length)
{
std::make_shared<session>(std::move(socket_))->write(msg, length);
}
private:
void do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
if (!ec)
{
std::make_shared<session>(std::move(socket_))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
tcp::socket socket_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_server <port>\n";
return 1;
}
boost::asio::io_service io_service;
server s(io_service, std::atoi(argv[1]));
std::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(io_service));
std::thread t1([&io_service]() {io_service.run();});
char msg[] = { 't', 'e', 's', 't' };
while(1)
{
sleep(5);
s.send(msg, 4);
}
t1.join();
std::cout << "t1 joined " << std::endl;
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}