博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Boost.Asio c++ 网络编程翻译(14)
阅读量:5023 次
发布时间:2019-06-12

本文共 3982 字,大约阅读时间需要 13 分钟。

保持活动
假如,你须要做以下的操作:
io_service service;
ip::tcp::socket sock(service);
char buff[512];
...
read(sock, buffer(buff));
在这个样例中,sock和buff的存在时间都必须比read()调用的时间要长。

也就是说,在调用read()返回之前,它们都必须有效。

这就是你期望的。你传给一个方法的全部參数在參数内部都必须有效。

当我们採用异步方式时,事情会变得越复杂。

io_service service;
ip::tcp::socket sock(service);
char buff[512];
void on_read(const boost::system::error_code &, size_t) {}
...
async_read(sock, buffer(buff), on_read);
在这个样例中。sock和buff的存在时间都必须比read()操作本身时间要长,可是read操作的时间我们是不知道的,由于它是异步的。
当使用socket缓冲区的时候,你会有一个buffer实例在异步调用时一直存在(使用boost::shared_array<>)。在这里,我们能够使用相同的方式。通过创建一个类并在其内部管理socket和它的读写缓冲区。

然后,对于全部的异步操作,我会传递一个包括智能指针的boost::bind仿函数:

using namespace boost::asio;   io_service service;   struct connection : boost::enable_shared_from_this
{
typedef boost::system::error_code error_code;       typedef boost::shared_ptr
ptr; connection() : sock_(service), started_(true) {} void start(ip::tcp::endpoint ep) {
sock_.async_connect(ep,                 boost::bind(&connection::on_connect, shared_from_this(),

_1)); }

void stop() {           if ( !started_) return;           started_ = false;           sock_.close();

}

bool started() { return started_; }   private:
void on_connect(const error_code & err) {           // here you decide what to do with the connection: read or
write           if ( !err)      do_read();
else            stop();       }
void on_read(const error_code & err, size_t bytes) {           if ( !started() ) return;           std::string msg(read_buffer_, bytes);
if ( msg == "can_login")else if ( msg.find("data ") == 0)else if ( msg == "login_fail")
do_write("access_data");process_data(msg);stop();
}void on_write(const error_code & err, size_t bytes) {

do_read(); }

void do_read() {
sock_.async_read_some(buffer(read_buffer_),                 boost::bind(&connection::on_read, shared_from_this(),

_1, _2)); }

void do_write(const std::string & msg) {           if ( !started() ) return;           // note: in case you want to send several messages before           //       doing another async_read, you'll need several write
buffers!           std::copy(msg.begin(), msg.end(), write_buffer_);           sock_.async_write_some(buffer(write_buffer_, msg.size()),
boost::bind(&connection::on_write, shared_from_this(),

_1, _2)); }

void process_data(const std::string & msg) {           // process what comes from server, and then perform another

write }

private:       ip::tcp::socket sock_;       enum { max_msg = 1024 };       char read_buffer_[max_msg];       char write_buffer_[max_msg];       bool started_;

};

int main(int argc, char* argv[]) {       ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"),
8001);       connection::ptr(new connection)->start(ep);

在全部异步调用中,我们传递一个boost::bind仿函数当作參数。

这个仿函数内部包括了一个智能指针,指向connection实例。仅仅要有一个异步操作等待时,Boost.Asio会保存boost::bind仿函数的拷贝,这个拷贝保存了指向连接实例的一个智能指针,从而保证connection实例保持活动。问题解决!

当然。connection类不过一个skeleton类;你须要依据你的需求对它进行调整(它看起来会和服务端的情况相当不同)。

你须要注意创建一个新的连接是相当简单的:connection::ptr(new connection)- >start(ep)。这种方法启动了到服务端的(异步)连接。

当你须要关闭这个连接时,调用stop()。

当实例被启动时(start()),它将会等待被连接。当连接发生时。on_connect()被调用。假设没有发生错误。它启动一个read操作(do_read())。

当read操作结束时,你解析这个消息;你应用的on_read()看起来会各种各样。

当你写回一个消息时,你须要把它复制到缓冲区。然后像我在do_write()方法中所做的一样将其发送出去,由于再一次,这个缓冲区须要在这个异步写操作中一直存活。最后须要注意的一点——当写回时,你须要指定写入的数量,否则。整个缓冲区都会被发送出去。

总结

网络api实际上要大得多,这个章节仅仅是一个參考,当你在实现你自己的网络应用时,你须要回来查看。

Boost.Asio实现了端点的概念。你能够觉得是IP和port。假设你不知道准确的IP,你能够使用resolver对象将主机名,比如www.yahoo.com转换为一个或多个IP地址。

我们也能够看到API的核心——socket类。Boost.Asio提供了TCP、UDP和 ICMP的实现。可是你能够用你自己的协议来对它进行扩展;当然,这个工作不适合胆小的人。

异步编程是必要之恶。你会明确为什么有时候须要它,尤其在写服务端的时候。调用service.run()来实现异步循环就已经能够让你非常开心。可是有时候你须要更进一步。尝试使用run_one()、poll()或者poll_one()。

当实现异步时,你能够用你自己方法来异步运行。使用service.post()或者service.dispatch()。

最后,为了使socket和缓冲区(read或者write)在整个异步操作的生命周期中一直活动,我们须要採取特殊的防护措施。你的连接类须要继承自enabled_shared_from_this,在内部保存它须要的缓冲区。并且每一个异步调用都要传递一个智能指针给this操作。

下一章会让你进行实战操作;在实现回显client/服务端应用时会有大量的上手编程。

转载于:https://www.cnblogs.com/bhlsheji/p/5252895.html

你可能感兴趣的文章
关于 UIWebView 几个高级用法
查看>>
maven创建的项目中无法创建src/main/java 解决方案
查看>>
华为软件开发云测评报告二:代码检查
查看>>
集合1
查看>>
js 原生 ajax
查看>>
关键词 virtual
查看>>
建造者模式(屌丝专用)
查看>>
UVALive 4730 Kingdom +段树和支票托收
查看>>
[APIO2010]特别行动队
查看>>
[SCOI2016]幸运数字
查看>>
SpringBoot 集成ehcache
查看>>
初步swift语言学习笔记2(可选类型?和隐式可选类型!)
查看>>
Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
查看>>
在Vs2012 中使用SQL Server 2012 Express LocalDB打开Sqlserver2012数据库
查看>>
在Macos下完美解决Adobe Dreamweaver CC 2018 汉化及操作方法
查看>>
【转】 Newtonsoft.Json高级用法
查看>>
CodeBlocks X64 SVN 编译版
查看>>
Excel催化剂开源第42波-与金融大数据TuShare对接实现零门槛零代码获取数据
查看>>
bug记录_signalr执行$.connnection.testhub结果为空
查看>>
【转】常用的latex宏包
查看>>