boost::asio实现一个echo服务器
以前使用ACE实现Server框架,但是觉得太笨重,决定采用boost.asio来写服务器程序:
1.服务器构建在linux上面;当然也可以在windows下运行
2.io部分采用非阻塞模式、业务逻辑部分采用同步线程池实现
3.封装io操作及状态,用户应用程序无需关心io详细操作
所以决定采用boost::asio框架来写服务器:
boost::asio::io_service提供了核心IO功能、和异步IO对象,它包括:
boost::asio::ip::tcp::socket
boost::asio::ip::tcp::acceptor
boost::asio::ip::udp::socket
boost::asio::deadline_timer
io_service支持线程安全、共享对象安全;调用run()函数未完成时会引发reset();
boost.asio异步方式的函数前面都加有async_前缀,函数参数中会要求放入一个回调函数(或仿函数);异步操作执行完后无论有没有完成都会立即返回,这时候可以处理其他事情,等到回调函数被调用就说明异步操作已经完毕。
boost.asio的很多回调函数值接收boost::system::error_code参数,在实际使用中是不够的,所以一般的仿函数都会携带一堆数据作为回调,或使用boost::bind来绑定一堆数据。
只有boost.asio.run()运行后回调对象才会被调用,否则即使系统已经完成了异步操作也不会有任何动作!
//下面是一个异步模式的简单的Tcp echo服务器
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp> using namespace boost::asio;
using boost::system::error_code;
using ip::tcp; struct CHelloWorld_Service
{
//类的初始化创建:设置io_service, 设置1000端口
CHelloWorld_Service(io_service &iosev)
:m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), ))
{
} //创建一个tcp的socket;且还是侦听
void start()
{
// 开始等待连接(非阻塞)
boost::shared_ptr<tcp::socket> psocket(new tcp::socket(m_iosev)); // 触发的事件只有error_code参数,所以用boost::bind把socket绑定进去
m_acceptor.async_accept(*psocket, boost::bind(&CHelloWorld_Service::accept_handler, this, psocket, _1) );
} // 有客户端连接时accept_handler触发
void accept_handler(boost::shared_ptr<tcp::socket> psocket, error_code ec)
{
if(ec) return; // 继续等待连接
start(); // 显示远程IP
std::cout << psocket->remote_endpoint().address() << std::endl; // 发送信息(非阻塞)
boost::shared_ptr<std::string> pstr(new std::string("hello async world!"));
psocket->async_write_some(buffer(*pstr),
boost::bind(&CHelloWorld_Service::write_handler, this, pstr, _1, _2)
);
} // 异步写操作完成后write_handler触发
void write_handler(boost::shared_ptr<std::string> pstr, error_code ec, size_t bytes_transferred)
{
if(ec)
std::cout<< "发送失败!" << std::endl;
else
std::cout<< *pstr << " 已发送" << std::endl;
} private:
io_service &m_iosev;
ip::tcp::acceptor m_acceptor;
}; int main(int argc, char* argv[])
{
//建立io服务器
io_service iosev; CHelloWorld_Service sev(iosev); //开始侦听socket的连接;和开始接收远程数据
sev.start(); //开始执行回调函数
iosev.run(); return ;
}
例子分析:
1.调用sev.start()开始接受客户端连接。async_accept()其实就是注册了一个回调函数;所以它会立即返回。
2.iosev.run()方法是一个循环,负责分发异步回调函数,只有当所有的异步操作执行完后才会返回。
3.为了保证start()中的m_accptor.async_accept操作所用的socket在整个异步操作期间都是有效的,而且以后所有的客户端连接进来后该socket都是有效地,这里的解决办法是使用一个带计数的智能指针,shared_ptr,并将该指针绑定到回调函数上。该智能指针的生存周期等同于sev的生存周期。
4.一旦有客户端连接,回调函数accept_handler()就会执行,在该函数中首先调用start()继续异步等待其他客户端连接;然后使用start()绑定进来的socket进行接收远程客户端的连接
5.例子程序中发送数据也使用了异步模式async_write_some,同样需要保证整个异步发送期间缓冲区的有效性,所以使用了shared_ptr<string>参数
6.对于客户端connect, read_some前面也可加入async_前缀,按照异步方式执行;
boost::asio实现一个echo服务器的更多相关文章
- (原创)如何使用boost.asio写一个简单的通信程序(二)
先说下上一篇文章中提到的保持io_service::run不退出的简单办法.因为只要异步事件队列中有事件,io_service::run就会一直阻塞不退出,所以只要保证异步事件队列中一直有事件就行了, ...
- (原创)如何使用boost.asio写一个简单的通信程序(一)
boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...
- boost::asio译文
Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENS ...
- 使用Boost.Asio编写通信程序
摘要:本文通过形像而活泼的语言简单地介绍了Boost::asio库的使用,作为asio的一个入门介绍是非常合适的,可以给人一种新鲜的感觉,同时也能让体验到asio的主要内容. Boost.Asio是一 ...
- Boost.Asio技术文档
Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENSE_1_ ...
- boost.asio包装类st_asio_wrapper开发教程(2013.12.8更新)(二)
如果你是偶然浏览到这里,请先看 源代码及例程下载地址:命令行:svn checkout http://st-asio-wrapper.googlecode.com/svn/trunk/ st-asio ...
- boost::asio 的同、异步方式
转自:http://blog.csdn.net/zhuky/archive/2010/03/10/5364574.aspx Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C ...
- boost Asio网络编程简介
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- boost asio 学习(一)io_service的基础
原文 http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio/ 编译环境 b ...
随机推荐
- SQL优化笔记一:索引和explain
目录 为什么需要优化SQL SQL优化的重点 索引 索引的结构 索引的优缺点总结: 索引的分类 索引操作 B树 实战 问题 数据库方面,我会使用MySQL来讲解 为什么需要优化SQL 性能低,执行时间 ...
- java io系列19之 CharArrayWriter(字符数组输出流)
本章,我们学习CharArrayWriter.学习时,我们先对CharArrayWriter有个大致了解,然后深入了解一下它的源码,最后通过示例来掌握它的用法. 转载请注明出处:http://www. ...
- hdfs.DataStreamer: Exception in createBlockOutputStream
在上传文件至 HDFS 提示如下信息 [root@h136 jdk1.8.0_202]# hadoop fs -put javafx-src.zip / 19/04/11 23:19:36 INFO ...
- angular学习一框架结构认识
angular学习所有内容均会与vue以及react框架进行对比. angular学习使用的编译器:webstorm 解决编译器屏蔽node_modules包问题: File-->setting ...
- javascript在计算浮点数(小数)不准确,解决方案
方案来自网络,实现简单,便于做加减乘除使用,由于项目临时要用记录下 如需要更加复杂的计算类库,可以考虑 math.js等知名类库 /** * floatTool 包含加减乘除四个方法,能确保浮点数运算 ...
- 细说REST API安全之认证授权
认证授权包含2个方面:(1)访问某个资源时必须携带用户身份信息,如:用户登录时返回用户access_token,访问资源时携带该参数.(2)检查用户是否具备访问当前资源(url或数据)的权限:访问资源 ...
- 在浏览器窗口中加载新的url
通常,在前端页面中如果需要跳转到指定页面,可以通过<a>标签进行跳转.而在某些情况下,比如ajax调用之后想直接跳转到指定页面,想跳转页面不能再用<a>标签实现.此时,可以通过 ...
- 【剑指offer】Java版代码(完整版)
原文地址:https://blog.csdn.net/baiye_xing/article/details/78428561 一.引言 <剑指offer>可谓是程序猿面试的神书了,在面试中 ...
- SQL Server进阶 遍历表的几种方法
https://www.cnblogs.com/mcgrady/p/4182486.html
- hadoop1.2.1的安装
前提:1.机器最好都做ssh免密登录,最后在启动hadoop的时候会简单很多 免密登录看免密登录 2.集群中的虚拟机最好都关闭防火墙,否则很麻烦 3集群中的虚拟机中必须安装jdk. 具体安装步骤如下: ...