Boost.Asio c++ 网络编程翻译(14)
也就是说,在调用read()返回之前,它们都必须有效。
这就是你期望的。你传给一个方法的全部參数在參数内部都必须有效。
当我们採用异步方式时,事情会变得越复杂。
然后,对于全部的异步操作,我会传递一个包括智能指针的boost::bind仿函数:
using namespace boost::asio;
io_service service;
struct connection : boost::enable_shared_from_this<connection> {
typedef boost::system::error_code error_code;
typedef boost::shared_ptr<connection> 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/服务端应用时会有大量的上手编程。
Boost.Asio c++ 网络编程翻译(14)的更多相关文章
- Boost.Asio c++ 网络编程翻译(20)
异步服务端 这个图表是相当复杂的:从Boost.Asio出来你能够看到4个箭头指向on_accept.on_read,on_write和on_check_ping. 着也就意味着你永远不知道哪个异步调 ...
- Boost.Asio c++ 网络编程翻译(26)
Boost.Asio-其他特性 这章我们讲了解一些Boost.Asio不那么为人所知的特性.标准的stream和streambuf对象有时候会更难用一些,但正如你所见.它们也有它们的益处.最后,你会看 ...
- Boost.Asio c++ 网络编程翻译(11)
*_at方法 这些方法在一个流上面做随机存取操作.你来指定read和write操作从什么地方開始(offset): async_read_at(stream, offset, buffer [, co ...
- Boost.Asio c++ 网络编程翻译(21)
同步VS异步 Boost.Asio的作者做了一个非常惊艳的工作:它能够让你在同步和异步中自由选择,从而更好的适应你的应用. 在之前的章节中,我们学习了每种类型应用的框架,比方同步client,同步服务 ...
- Boost.Asio c++ 网络编程翻译(16)
TCP异步服务端 核心功能和同步服务端的功能类似,例如以下: class talk_to_client : public boost::enable_shared_from_this<talk_ ...
- Boost.Asio c++ 网络编程翻译(10)
read/write方法 这些方法对一个流进行读写操作(能够是套接字,或者其它表现的像流的类): async_read(stream, buffer [, completion],handler):这 ...
- Boost.Asio c++ 网络编程翻译(18)
同步服务端 同步服务端也相当简单.它须要两个线程,一个负责接收新的client.另外一个负责处理已经存在的client. 它不能使用单线程:等带一个新的client是一个堵塞操作,所以我们须要另外一个 ...
- 《Unix 网络编程》14:高级 I/O 函数
高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...
- boost.asio系列——socket编程
asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程. 客户端 客户端的代码如下: #include &l ...
随机推荐
- linux----LAMP之编译安装apache
第一步:解决依赖.安装apr.apr-util. apr-1.5.4.tar.gz下载地址:http://yunpan.cn/cFBzgsC3rDcyR 访问密码 4c82 apr-util-1.5 ...
- MYSQL 二进制还原
解决方法: mysqlbinlog bin_log_file_path_and_name | mysql -uroot -p 如: mysqlbinlog E:\DB\mysql_log\mysql_ ...
- 5款免费Windows远程连接Linux桌面软件(VNC客户端)
不论我们出于何种的用途目的,很多朋友有需要用到VNC链接Linux桌面环境,之前老左有分享过VNC Viewer绿色软件,昨天有朋友提出来使用之后登录远程桌面的界面.分辨率等有些色差.流畅程度 ...
- Delphi Window 消息大全使用详解
WM_CTLCOLORSTATIC = $0138; 当一个静态控件将要被绘制时发送此消息给它的父窗口:通过响应这条消息,所有者窗口可以通过使用给定的相关显示设备的句柄来设置静态控件的文本和背景颜色 ...
- C语言的本质(2)——二进制、八进制、十六进制与十进制
二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是"逢二进一",借位规则是"借一当二",由18世纪德国数理哲 ...
- SELinux开关导致mysql服务启动不了
http://www.jb51.net/article/36187.htm 网站突然连接不上数据库,于是朋友直接重启了一下服务器.进到cli模式下,执行 service myqsld start 发现 ...
- linux centos 配置 svn 服务器
首先介绍一下吧,Subversion(SVN) 是一个开源的版本控制系統, 也就是说 Subversion 管理着随时间改变的数据. 这些数据放置在一个中央资料档案库 (repository) 中. ...
- 一个利用扩展方法的实例:AttachDataExtensions
扩展方法是C# 3.0(老赵对VB不熟)中最简单,也是最常用的语言特性之一.这是老赵自以为的一个简单却不失经典的实例: [AttributeUsage(AttributeTargets.All, Al ...
- jQuery模拟原生态App上拉刷新下拉加载
jQuery模拟原生态App上拉刷新下拉加载效果代码,鼠标上拉时会显示loading字样,并且会模拟加载一条静态数据,支持触屏设备使用. <!doctype html> <html ...
- 简单的Ajax
ajax获取时间的html代码 <head> <meta http-equiv="Content-Type" content="text/html; c ...