У меня есть программное обеспечение, которое я хотел бы сделать TCP-клиентом.Я не знаю, является ли это лучшей архитектурой, но в моем программном обеспечении я создал поток, который будет использоваться для сетевого ввода-вывода.Если есть лучшая архитектура, я был бы признателен за некоторые советы и рекомендации.
Оба потока имеют ссылку на объект boost :: asio :: io_service и объект Session, который инкапсулирует объект сокета.Объект sesson выглядит примерно так:
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_;
};
В цикле выполнения потока ввода-вывода вызывается метод start () объекта сеанса, который подключается к серверу.(Это работает, кстати).Затем поток находится в цикле, вызывающем метод run () для объекта службы ввода-вывода [io_service_.run ()] для запуска событий.
Основной поток вызывает метод write () сеансакогда он хочет отправить данные, и объект сеанса вызывает boost :: async_write с данными для записи, а затем метод обратного вызова, который является членом объекта сеанса (handle_write).
Пока у меня есть I /О поток, соединяющийся с сервером, я не могу получить метод handle_write для запуска.Я проверил, что основной поток вызывает объект сеанса и выполняет async_write () в сокете.Просто обратный вызов никогда не срабатывает.Я также не вижу никаких данных на стороне сервера или по проводам с помощью tcpdump.
Есть идеи, где может быть моя проблема?Есть ли лучший способ организовать архитектуру?Более того, я не хочу блокировать основной поток, выполняя ввод / вывод.
Вот код, который порождает поток 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")));
// spawn new thread for the network I/O endpoint
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){ // improve this later
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";
}
}