Boost.Asio c++ 网络编程翻译(18)
同步服务端
它不能使用单线程;等带一个新的client是一个堵塞操作,所以我们须要另外一个线程来处理已经存在的client。
void accept_thread() {
ip::tcp::acceptor acceptor(service,
ip::tcp::endpoint(ip::tcp::v4(),
8001));
while ( true) {
client_ptr new_( new talk_to_client);
acceptor.accept(new_->sock());
boost::recursive_mutex::scoped_lock lk(cs);
clients.push_back(new_);
} }
void handle_clients_thread() {
while ( true) {
boost::this_thread::sleep( millisec(1));
boost::recursive_mutex::scoped_lock lk(cs);
for(array::iterator b = clients.begin(),e = clients.end(); b
!= e; ++b)
(*b)->answer_to_client();
// 删除已经超时的客户端
clients.erase(std::remove_if(clients.begin(), clients.end(),
boost::bind(&talk_to_client::timed_out,_1)),
clients.end());
}
}
int main(int argc, char* argv[]) {
boost::thread_group threads;
threads.create_thread(accept_thread);
threads.create_thread(handle_clients_thread);
threads.join_all();
}
typedef boost::shared_ptr<talk_to_client> client_ptr;
typedef std::vector<client_ptr> array;
array clients;
boost::recursive_mutex cs; // 用线程安全的方式訪问客户端数组
struct talk_to_client : boost::enable_shared_from_this<talk_to_client>
{
talk_to_client() { ... }
std::string username() const { return username_; }
void answer_to_client() {
try {
read_request();
process_request();
} catch ( boost::system::system_error&) {
stop(); }
if ( timed_out())
stop();
}
void set_clients_changed() { clients_changed_ = true; }
ip::tcp::socket & sock() { return sock_; }
bool timed_out() const {
ptime now = microsec_clock::local_time();
long long ms = (now - last_ping).total_milliseconds();
return ms > 5000 ;
}
void stop() {
boost::system::error_code err; sock_.close(err);
}
void read_request() {
if ( sock_.available())
read_)); }
... private:
already_read_ += sock_.read_some(
buffer(buff_ + already_read_, max_msg - already_
// ... same as in Synchronous Client
bool clients_changed_;
ptime last_ping;
};
它仅仅有在存在有效数据的情况才读取,这种话,服务端永远不会堵塞:
void process_request() {
bool found_enter = std::find(buff_, buff_ + already_read_, '\n')
< buff_ + already_read_;
if ( !found_enter)
return; // message is not full
// process the msg
last_ping = microsec_clock::local_time();
size_t pos = std::find(buff_, buff_ + already_read_, '\n') -
buff_;
std::string msg(buff_, pos);
std::copy(buff_ + already_read_, buff_ + max_msg, buff_);
already_read_ -= pos + 1;
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();
else std::cerr << "invalid msg " << msg << std::endl;
}
void on_login(const std::string & msg) {
std::istringstream in(msg);
in >> username_ >> username_;
write("login ok\n");
update_clients_changed();
}
void on_ping() {
write(clients_changed_ ? "ping client_list_changed\n" : "ping
ok\n");
clients_changed_ = false;
}
void on_clients() {
std::string msg;
{ boost::recursive_mutex::scoped_lock lk(cs);
for( array::const_iterator b = clients.begin(), e = clients.
end() ;
b != e; ++b)
msg += (*b)->username() + " ";
}
write("clients " + msg + "\n");
}
void write(const std::string & msg) { sock_.write_some(buffer(msg)); }
Boost.Asio c++ 网络编程翻译(18)的更多相关文章
- Boost.Asio c++ 网络编程翻译(20)
异步服务端 这个图表是相当复杂的:从Boost.Asio出来你能够看到4个箭头指向on_accept.on_read,on_write和on_check_ping. 着也就意味着你永远不知道哪个异步调 ...
- 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系列——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 ...
随机推荐
- 00018_流程控制语句switch
1.选择结构switch switch 条件语句也是一种很常用的选择语句,它和if条件语句不同,它只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码. 2.switch语句的语法格式 swit ...
- Java连接Access数据库的那些坑
Java 使用 JDBC 连接Access数据库 需要掌握的技能 1.Java SE基本技术 2.懂点JDBC技术 能够学到如何使用Java正确的连接JDBC 环境 window8.1 64位 jdk ...
- 十分钟了解socket
socket通讯方式------socket是TCP/IP协议的网络数据通讯接口(一种底层的通讯的方式).socket是IP地址和端口号的组合.例如:192.168.1.100:8080 原理就是TC ...
- Flask_单例模式
在flask实现单例模式的方法有多种: 这里我们列举五种,行吗? 第一种: 国际惯例:基于文件导入 第二种: 基于类的单例模式: 它又分两种: 一种加锁,一种不加锁. 不加锁的话,可以并发,但是我们的 ...
- wordpress 使用wp_head()函数
wp_head()的作用: 在WordPress主题中使用此函数控制<head>…</head>之间的标签内容. 以通过header.php模板文件输出html中的head标签 ...
- JAVA-STRUTS-2x的项目配置
首先是web.xml的配置,这个是项目加载的开始. <display-name></display-name> <!--struts2配置开始--> <fil ...
- Spider爬虫-get、post请求
1:概念: 爬虫就是通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程. 2:python爬虫与其他语言的比较: (1)php爬虫弊端:多进程多线程支持的不好 (2)java:代码臃肿,重 ...
- 【瓜分5000元奖金】Wannafly挑战赛13
链接:https://www.nowcoder.com/acm/contest/80/A来源:牛客网 zzy的小号 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他 ...
- API生命周期第二阶段——设计:采用swagger进行API描述、设计
本篇博客主要是以swagger为依托,介绍API生命周期的第二个阶段--设计!在详细介绍之前,我必须声明一点:如果是想了解swagger和项目框架的集成的,这里没有.我要介绍的swagger进行的AP ...
- poj3255 Roadblocks 次短路
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10098 Accepted: 3620 Descr ...