首页 > 代码库 > Boost.Asio c++ 网络编程翻译(23)
Boost.Asio c++ 网络编程翻译(23)
客户端应用中的异步I/O
主流程和同步客户端应用有点类似,不同的是Boost.Asio每次都位于async_read和async_write请求中间。
第一种情况是我在第四章 客户端和服务端 中实现过的。你应该还记得在每个异步操作结束的时候,我都启动另外一个异步操作,这样service.run()方法才不会结束。
为了适应第二种情况,你需要使用下面的代码片段:
void on_connect() {
do_read();
}
void do_read() {
async_read(sock_, buffer(read_buffer_),
MEM_FN2(read_complete,_1,_2), MEM_FN2(on_read,_1,_2));
}
void on_read(const error_code & err, size_t bytes) {
if ( err) stop();
if ( !started() ) return;
std::string msg(read_buffer_, bytes);
if ( msg.find("clients") == 0) on_clients(msg);
else ...
}
void on_clients(const std::string & msg) {
std::string clients = msg.substr(8);
std::cout << username_ << ", new client list:" << clients ;
do_write("clients ok\n");
}
注意只要我们成功连接上,我们就开始从服务端读取。每个on_[event]方法都会通过写一个回复给服务端的方式来结束我们。
使用异步的美好在于你可以使用Boost.Asio进行管理,从而把I/O网络操作和其他异步操作结合起来。尽管它的流程不像同步的流程那么清晰,你仍然可以用同步的方式来想象它。
假设,你从一个web服务器读取文件然后把它们保存到一个数据库中(异步地)。你可以把这个过程想象成下面的流程图:
服务端应用的异步I/O
现在要展示的是两个普遍的情况,情况1(拉取)和情况2(推送)
第一种情况同样是我在第4章 客户端和服务端中实现的异步服务端。在每一个异步操作最后,我都会启动另外一个异步操作,这样的话service.run()久不会结束。
现在要展示的是被剪裁过的框架代码。下面是talk_to_client类所有的成员:
void start() {
...
do_read(); // first, we wait for client to login
}
void on_read(const error_code & err, size_t bytes) {
std::string msg(read_buffer_, bytes);
if ( msg.find("login ") == 0) on_login(msg);
else if ( msg.find("ping") == 0) on_ping();
else ... }
void on_login(const std::string & msg) {
std::istringstream in(msg);
in >> username_ >> username_;
do_write("login ok\n");
}
void do_write(const std::string & msg) {
std::copy(msg.begin(), msg.end(), write_buffer_);
sock_.async_write_some( buffer(write_buffer_, msg.size()),
MEM_FN2(on_write,_1,_2));
}
void on_write(const error_code & err, size_t bytes) {
do_read(); }
简单来说,我们始终等待一个read操作,而且只要一发生,我们就处理然后将结果返回给客户端。
我们把上述代码进行修改就可以完成一个推送服务端
void start() {
...
on_new_client_event();
}
void on_new_client_event() {
std::ostringstream msg;
msg << "client count " << clients.size();
for ( array::const_iterator b = clients.begin(), e = clients.
end();
(*b)->do_write(msg.str());
}
void on_read(const error_code & err, size_t bytes) {
std::string msg(read_buffer_, bytes);
// basically here, we only acknowledge
// that our clients received our notifications
}
void do_write(const std::string & msg) {
std::copy(msg.begin(), msg.end(), write_buffer_);
sock_.async_write_some( buffer(write_buffer_, msg.size()),
MEM_FN2(on_write,_1,_2));
}
void on_write(const error_code & err, size_t bytes) {
do_read(); }
只要有一个事件发生,我们假设是on_new_client_event,所有需要被通知到的客户端都被发送一条信息。当它们回复时,我们简单认为他们已经确认收到事件。注意我们永远不会把正在等待的异步操作用尽(所以,service.run()不会结束),因为我们一直在等待一个新的客户端:
ip::tcp::acceptor acc(service, ip::tcp::endpoint(ip::tcp::v4(),
8001));
void handle_accept(talk_to_client::ptr client, const error_code & err)
{
client->start();
talk_to_client::ptr new_client = talk_to_client::new_();
acc.async_accept(new_client->sock(), bind(handle_accept,new_
client,_1));
}
Boost.Asio c++ 网络编程翻译(23)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。