Boost.Asio c++ 网络编程翻译(20)
异步服务端
着也就意味着你永远不知道哪个异步调用是下一个完毕的调用。可是你能够确定的是它是这4个操作中的一个。
ip::tcp::acceptor acceptor(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_();
acceptor.async_accept(new_client->sock(),
boost::bind(handle_accept,new_client,_1));
}
int main(int argc, char* argv[]) {
talk_to_client::ptr client = talk_to_client::new_();
acceptor.async_accept(client->sock(),boost::bind(handle_accept,client,_1));
service.run();
}
class talk_to_client; typedef boost::shared_ptr<talk_to_client>
client_ptr;
typedef std::vector<client_ptr> array;
array clients;
class talk_to_client : public boost::enable_shared_from_this<talk_to_
client>
, boost::noncopyable {
talk_to_client() { ... }
public:
typedef boost::system::error_code error_code;
typedef boost::shared_ptr<talk_to_client> ptr;
void start() {
started_ = true;
clients.push_back( shared_from_this());
last_ping = boost::posix_time::microsec_clock::local_time();
do_read(); //首先,我们等待客户端连接
}
static ptr new_() { ptr new_(new talk_to_client); return new_; }
void stop() {
if ( !started_) return;
started_ = false;
sock_.close();
ptr self = shared_from_this();
array::iterator it = std::find(clients.begin(), clients.end(),
self);
clients.erase(it);
update_clients_changed();
}
bool started() const { return started_; }
ip::tcp::socket & sock() { return sock_;}
std::string username() const { return username_; }
void set_clients_changed() { clients_changed_ = true; }
…
private:
ip::tcp::socket sock_;
enum { max_msg = 1024 };
char read_buffer_[max_msg];
char write_buffer_[max_msg];
bool started_;
std::string username_;
deadline_timer timer_;
boost::posix_time::ptime last_ping;
bool clients_changed_;
};
我会用talk_to_client或者talk_to_server来调用connection类,从而使你更明确我所说的内容。
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("login ") == 0) on_login(msg);
else if ( msg.find("ping") == 0) on_ping();
else if ( msg.find("ask_clients") == 0) on_clients();
}
void on_login(const std::string & msg) {
std::istringstream in(msg);
in >> username_ >> username_;
do_write("login ok\n");
update_clients_changed();
}
void on_ping() {
do_write(clients_changed_ ? "ping client_list_changed\n" : "ping
ok\n");
clients_changed_ = false;
}
void on_clients() {
std::string msg;
for(array::const_iterator b =clients.begin(),e =clients.end(); b
!= e; ++b)
msg += (*b)->username() + " ";
do_write("clients " + msg + "\n");
}
void do_ping() { do_write("ping\n"); }
void do_ask_clients() { do_write("ask_clients\n"); }
void on_write(const error_code & err, size_t bytes) { do_read(); }
void do_read() {
async_read(sock_, buffer(read_buffer_),
MEM_FN2(read_complete,_1,_2), MEM_FN2(on_read,_1,_2));
post_check_ping();
}
void do_write(const std::string & msg) {
if ( !started() ) return;
std::copy(msg.begin(), msg.end(), write_buffer_);
sock_.async_write_some( buffer(write_buffer_, msg.size()),
MEM_FN2(on_write,_1,_2));
}
size_t read_complete(const boost::system::error_code & err, size_t
bytes) {
// ... as before
}
void on_check_ping() {
ptime now = microsec_clock::local_time();
if ( (now - last_ping).total_milliseconds() > 5000)
stop();
last_ping = boost::posix_time::microsec_clock::local_time();
}
void post_check_ping() {
timer_.expires_from_now(boost::posix_time::millisec(5000));
timer_.async_wait( MEM_FN(on_check_ping));
}
我建议你自己执行这些样例,由于从头到尾读一次代码能加强你对本章展示应用的理解。
我们已经避免了一些诸如内存泄漏和死锁的低级错误。全部的编码都是框架式的。这样你就能够依据你自己的需求对它们进行扩展。
Boost.Asio c++ 网络编程翻译(20)的更多相关文章
- Boost.Asio c++ 网络编程翻译(14)
保持活动 假如,你须要做以下的操作: io_service service; ip::tcp::socket sock(service); char buff[512]; ... read(sock, ...
- 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是一个堵塞操作,所以我们须要另外一个 ...
- boost.asio系列——socket编程
asio的主要用途还是用于socket编程,本文就以一个tcp的daytimer服务为例简单的演示一下如何实现同步和异步的tcp socket编程. 客户端 客户端的代码如下: #include &l ...
- 使用boost.asio实现网络通讯
#include <boost/asio.hpp> #define USING_SSL //是否加密 #ifdef USING_SSL #include <boost/asio/ss ...
随机推荐
- php 之 json格式
/*JSON语法数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组 JSON 数据的书写格式是:名称/值对名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值;如"myw ...
- sass用法
可能刚开始我们学习前端的时候都习惯用html+css.来做网页,但是我们发现css有很多重复的代码或者是你要改里面的图片或者文字还有去诶个的找很麻烦,所以我们就用sass来简化它. 首先我们需要安装一 ...
- 【python】python程序分行写符号
方法1,用括号 >>> 3+4+(5+ 6)18 方法2 用 \ >>> 3+5+\ 412
- Amazon's NoSQL Journey and AWS Operations
AWS: Amazon Web Services 提供了一整套基础设施和应用程序服务,使您几乎能够在云中运行一切应用程序:从企业应用程序和大数据项目,到社交游戏和移动应用程序. 计算类: EC2:弹性 ...
- chmod 命令
来源网址: http://www.2cto.com/os/201205/130236.html http://www.cnblogs.com/younes/archive/2009/11/20/160 ...
- ASP.NET MVC轻教程 Step By Step 10——模型验证
在使用表单获取用户输入的数据时,我们必须对数据进行有效性验证,因为来自网络的信息都是不可信的.同时也要给用户即时的反馈,避免让用户感到困惑.这就涉及到数据验证的范畴. 数据验证最直接的做法是在服务器端 ...
- 一张图看懂DNS域名解析全过程
DNS域名解析是互联网上非常重要的一项服务,上网冲浪(还有人在用这个词吗?)伴随着大量DNS服务来支撑,而对于网站运营来说,DNS域名解析的稳定可靠,意味着更多用户的喜欢,更好的SEO效果和更大的访问 ...
- 静态代理VS动态代理
代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委 ...
- BZOJ 3672 购票
Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国\(n\)个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与 ...
- -_-#【Better Code】throttle / debounce
浅谈javascript的函数节流 javascript函数的throttle和debounce throttle 疯狂触发事件,固定步调执行 debounce 疯狂触发事件,不会执行 var res ...