【发布时间】:2011-02-24 21:48:01
【问题描述】:
我有一些软件想制作一个 TCP 客户端。我不知道这是否是最好的架构,但在我的软件中,我生成了一个用于网络 I/O 的线程。如果有更好的架构,我会很感激一些指针和建议。
两个线程都引用了 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_;
};
在 I/O 线程运行循环中,会调用连接到服务器的会话对象的 start() 方法。 (这行得通,顺便说一句)。然后,线程处于循环中,调用 I/O 服务对象 [io_service_.run()] 上的 run() 方法来触发事件。
主线程要发送数据时调用会话的write()方法,会话对象调用boost::async_write将要写入的数据,然后是会话对象成员的回调方法(句柄写)。
虽然我有连接到服务器的 I/O 线程,但我无法触发 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")));
// 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";
}
}
【问题讨论】:
-
我们可以看看您的 start()、write()、handle_connect() 和 handle_write() 函数的代码吗?
-
您的示例不完整,请发布更多代码。以您描述的方式使用 asio 是很常见的,一个主线程和一个调用 io_service 事件循环的第二个线程。
-
按要求添加了代码。我基本上从 HTTP 客户端示例中获取了大部分内容。
-
您更新的问题仍然不完整,我们需要查看
Session类定义。 -
很抱歉,希望这将提供所有需要的信息。谢谢。
标签: c++ boost asynchronous boost-asio