基于c++11新标准开发一个支持多线程高并发的网络库
背景
新的c++11标准出后,c++语法得到了非常多的扩展,比起以往不论什么时候都要灵活和高效,提高了程序编码的效率,为软件开发者节省了不少的时间。
之前我也写过基于ACE的网络server框架,但ACE毕竟有些臃肿。内部对象关系错综复杂,easy给人造成仅仅见树木不见森林的错觉。 所以打算用c++11开发一个较为简洁,高效,支持高并发的网络库。
开源
基础的结构已经开发完毕,代码也开源在github上。网址是 https://github.com/lichuan/fly 欢迎各位提出建议。
结构
fly网络库主要分为base模块,task模块,net模块。base主要是一些最基础的功能集合。包含日志。id分配器,随机数,队列等。task主要封装了任务抽象以及任务调度运行等功能;net主要是实现网络层面的封装。为上层使用者提供简单易用的网络接口,这也是fly库的核心模块。实现了解析协议的Parser封装,负责监听网络的Acceptor,负责网络连接io功能的Poller封装体,在Parser、Acceptor、和Poller的基础上还进一步封装了作为server来使用的Server类和作为client来使用的Client类,这两个类是fly库的核心类,上层的应用能够直接使用Server对象和Client对象来建立网络server。作为网络连接概念的Connection对象则是通过std::shared_ptr来管理它的生命周期的,shared_ptr内置共享对象的功能大大地简化了网络连接生命期的管理。
协议
fly库的网络协议基于全世界最通用的json格式。而它的解析则依赖于rapidjson第三方库来完毕。
协议组成例如以下:
|长度字段|{协议类型:类型值,协议命令:命令值,其它json字段}|
协议类型和协议命令组成了二级消息字,就能够组合出各种约定的协议了。
应用
fly库的test文件夹提供了一个简单的例程。当中test_server.cpp代码例如以下:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* _______ _ *
* ( ____ \ ( \ |\ /| *
* | ( \/ | ( ( \ / ) *
* | (__ | | \ (_) / *
* | __) | | \ / *
* | ( | | ) ( *
* | ) | (____/\ | | *
* |/ (_______/ \_/ *
* *
* *
* fly is an awesome c++11 network library. *
* *
* @author: lichuan *
* @qq: 308831759 *
* @email: 308831759@qq.com *
* @github: https://github.com/lichuan/fly *
* @date: 2015-06-10 13:34:21 *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include <unistd.h>
#include <unordered_map>
#include "fly/init.hpp"
#include "fly/net/server.hpp"
#include "fly/base/logger.hpp" using namespace std::placeholders; class Test_Server : public fly::base::Singleton<Test_Server>
{
public:
bool allow(std::shared_ptr<fly::net::Connection> connection)
{
return true;
} void init(std::shared_ptr<fly::net::Connection> connection)
{
std::lock_guard<std::mutex> guard(m_mutex);
m_connections[connection->id()] = connection;
LOG_INFO("connection count: %u", m_connections.size());
} void dispatch(std::unique_ptr<fly::net::Message> message)
{
std::shared_ptr<fly::net::Connection> connection = message->get_connection();
const fly::net::Addr &addr = connection->peer_addr();
LOG_INFO("recv message from %s:%d raw_data: %s", addr.m_host.c_str(), addr.m_port, message->raw_data().c_str());
} void close(std::shared_ptr<fly::net::Connection> connection)
{
LOG_INFO("close connection from %s:%d", connection->peer_addr().m_host.c_str(), connection->peer_addr().m_port);
std::lock_guard<std::mutex> guard(m_mutex);
m_connections.erase(connection->id());
LOG_INFO("connection count: %u", m_connections.size());
} void be_closed(std::shared_ptr<fly::net::Connection> connection)
{
LOG_INFO("connection from %s:%d be closed", connection->peer_addr().m_host.c_str(), connection->peer_addr().m_port);
std::lock_guard<std::mutex> guard(m_mutex);
m_connections.erase(connection->id());
LOG_INFO("connection count: %u", m_connections.size());
} void main()
{
//init library
fly::init(); //init logger
fly::base::Logger::instance()->init(fly::base::DEBUG, "server", "./log/"); //test tcp server
std::unique_ptr<fly::net::Server> server(new fly::net::Server(fly::net::Addr("127.0.0.1", 8899),
std::bind(&Test_Server::allow, this, _1),
std::bind(&Test_Server::init, this, _1),
std::bind(&Test_Server::dispatch, this, _1),
std::bind(&Test_Server::close, this, _1),
std::bind(&Test_Server::be_closed, this, _1))); if(server->start())
{
LOG_INFO("start server ok!");
server->wait();
}
else
{
LOG_ERROR("start server failed");
}
} private:
std::unordered_map<uint64, std::shared_ptr<fly::net::Connection>> m_connections;
std::mutex m_mutex;
}; int main()
{
Test_Server::instance()->main();
}
Server对象构造时会要求传入监听地址和回调函数,当Server对象start启动时,fly库底层就会建立对应的Poller、Parser、Acceptor对象,假设想实现多线程Poller和Parser,则需传入并发线程数量就可以,回调函数说明例如以下:
allow_cb:当有新的连接到达时调用。来推断是否同意该连接的注冊。
init_cb:当把连接对象注冊到某一个Poller和Parser后调用,进行初始化处理。
dispatch_cb:当有消息到达时会调用,进行消息派发。
close_cb:主动关闭连接对象时调用。
be_closed_cb:检測到对端关闭连接对象时调用。
test_client.cpp主要使用Client对象来连接到某一个server,相同Client构造时也须要传入回调函数,其作用与Server构造时传入的回调一样。
基于c++11新标准开发一个支持多线程高并发的网络库的更多相关文章
- python 开发一个支持多用户在线的FTP
### 作者介绍:* author:lzl### 博客地址:* http://www.cnblogs.com/lianzhilei/p/5813986.html### 功能实现 作业:开发一个支持多用 ...
- Python3学习之路~8.6 开发一个支持多用户在线的FTP程序-代码实现
作业: 开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp s ...
- C++11新标准学习
<深入理解C++11:C++11新特性解析与应用> <华章科技:深入理解C++11:C++11新特性解析与应用>一共8章:第1章从设计思维和应用范畴两个维度对C++11新标准中 ...
- C++11新标准:nullptr关键字
一.nullptr的意义 1.NULL在C中的定义 #define NULL (void*)0 2.NULL在C++中的定义 #ifndef NULL #ifdef __cplusplus #defi ...
- C++11新标准:decltype关键字
一.decltype意义 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了).为了满足这一需求,C++11新标准引入了decltype类型 ...
- C++11新标准:auto关键字
一.auto意义 编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型,然后要做到这一点并非那么容易.为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能 ...
- [开源] gnet: 一个轻量级且高性能的 Golang 网络库
Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...
- c++11新标准for循环和lambda表达式
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- 30分钟用Restful ABAP Programming模型开发一个支持增删改查的Fiori应用
2016年时,Jerry曾经写过一系列关于SAP Fiori Smart Template(现在更名为Fiori Elements了)的博客,介绍了所谓的MDD开发方法论 - Metadata Dri ...
随机推荐
- hdu 4135 Co-prime (素数打表+容斥原理)
题目链接 题意:问从A到B中与N互素的个数. 题解: 利用容斥原理:先求出与n互为素数的个数. 可以先将 n 进行素因子分解,然后用区间 x 除以 素因子,就得到了与 n 的 约数是那个素因子的个数, ...
- python正则的中文处理(转)
匹配中文时,正则表达式规则和目标字串的编码格式必须相同 print sys.getdefaultencoding() text =u"#who#helloworld#a中文x#" ...
- logging模块介绍
在我们的实际开发过程中,我们有时候需要记录一些重要操作,或者程序运行情况,我们就需要在程序里面写入日志,来达到更快的排错跟记录重要操作的目的.在Python中logging模块就很好的解决了这个问题, ...
- python3下安装aiohttp遇到过的那些坑
python3下安装aiohttp遇到过的那些坑 最近需要用到aiohttp这个库,在安装过程中遇到很多坑.google.baidu后,依然没有找到合适的解决方案. 后来通过去python官方的PyP ...
- cobol COMP-3最后1位
"C" hex is positive, "D" hex is negative, and "F" hex is unsigned.
- 【Trie】【kd-tree】计蒜客17122 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 I. Barty's Computer
题意:2种操作:①往集合里添加一个串 ②给你四个小串a b c d,问你集合里有几个串S满足S=a+S1+b+c+S2+d的形式.S1 S2可以为空,并且a+S1+b=c+S2+d. 就搞四颗Trie ...
- python基础之递归,匿名,内置函数
递归函数: 什么是递归函数? 函数递归调用:在调用一个函数的过程中,又直接或间接地调用了该函数本身. 递归必须要有两个明确的阶段: ①递推:一层一层递归调用下去,强调:每进入下一层问题规模减少 ②回溯 ...
- [NOIp2016提高组]天天爱跑步
题目大意: 有一棵n个点的树,每个点上有一个摄像头会在第w[i]秒拍照. 有m个人再树上跑,第i个人沿着s[i]到t[i]的路径跑,每秒钟跑一条边. 跑到t[i]的下一秒,人就会消失. 问每个摄像头会 ...
- java笔记之面向对象
一.面向过程与面向对象的区别 1 面向过程:主要关注点是:实现的具体过程,因果关系[集成显卡的开发思路] * 优点:对于业务逻辑比较简单的程序,可以达到快速开发,前期投入成本较低. * 缺点:采用面向 ...
- 安装gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabi交叉编译器
1.开发平台 虚拟机:VMware 12 操作系统:Ubuntu 14.04 64bit 2.准备ARM交叉编译工具包 编译uboot和linux kernel都需要ARM交叉工具链支持,这里使用Li ...