基于c++11新标准开发一个支持多线程高并发的网络库

原创 2015年07月09日 17:39:41

背景

        新的c++11标准出后,c++语法得到了很多的扩展,比起以往任何时候都要灵活和高效,提高了程序编码的效率,为软件开发人员节省了不少的时间。 之前我也写过基于ACE的网络服务器框架,但ACE毕竟有些臃肿,内部对象关系错综复杂,容易给人造成只见树木不见森林的错觉。 所以打算用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类和作为客户端来使用的Client类,这两个类是fly库的核心类,上层的应用可以直接使用Server对象和Client对象来建立网络服务器。作为网络连接概念的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对象来连接到某一个服务器,同样Client构造时也需要传入回调函数,其作用与Server构造时传入的回调一样。

C++并发与多线程

  • 2017年08月30日 10:28
  • 4.72MB
  • 下载

发布一个高性能的Reactor模式的C++网络库:evpp

发布一个高性能的Reactor模式的C++网络库。evpp是一个基于libevent开发的现代化的支持C++11特性的高性能网络库,自带TCP/UDP/HTTP等协议的异步非阻塞式的服务器和客户端库。...
  • zieckey
  • zieckey
  • 2017年03月19日 22:50
  • 3018

C++并发服务器的实现

  • 2014年09月28日 02:13
  • 4.14MB
  • 下载

高性能C++网络库libtnet实现:IOLoop

libtnet采用的是prefork + event loop的架构方式,在最新的linux系统中,提供了timerfd,eventfd,signalfd,加上原先的socket,大部分功能都可以抽象...
  • siddontang
  • siddontang
  • 2013年12月05日 23:10
  • 3457

值得推荐的C/C++框架和库 (真的很强大)

值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的...
  • maweifei
  • maweifei
  • 2016年07月08日 11:53
  • 5277

值得推荐的C/C++框架和库 (真的很强大)

值得学习的C语言开源项目 - 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作...
  • xiaoxiaoyeyaya
  • xiaoxiaoyeyaya
  • 2015年01月09日 00:52
  • 143816

C++ 高性能服务器网络框架设计细节

GitChat 作者:范蠡 这篇文章我们将介绍服务器的开发,并从多个方面探究如何开发一款高性能高并发的服务器程序。需要注意的是一般大型服务器,其复杂程度在于其业务,而不是在于其代码工程的基本框架。大...
  • GitChat
  • GitChat
  • 2017年10月12日 15:48
  • 4096

值得推荐的C/C++框架和库 (真的很强大)

目录(?)[-] 值得学习的C语言开源项目- 1 Webbench- 2 Tinyhttpd- 3 cJSON- 4 CMockery- 5 Libev- 6 Memcached- 7 Lua- 8...
  • u011629814
  • u011629814
  • 2016年04月06日 23:38
  • 4265

值得推荐的C/C++框架和库 (真的很强大)

本篇文章主要介绍了"值得推荐的C/C++框架和库 (真的很强大)",主要涉及到方面的内容,对于C/C++教程感兴趣的同学可以参考一下: 得学习的C语言开源项目- 1. Webbench Webbenc...
  • mfcing
  • mfcing
  • 2015年10月09日 21:13
  • 20317

C++网络框架和库

C++网络方面学习
  • u010913001
  • u010913001
  • 2016年09月09日 15:50
  • 1089
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于c++11新标准开发一个支持多线程高并发的网络库
举报原因:
原因补充:

(最多只允许输入30个字)