I:跨平台设计基础

在windows下使用0字节的WSARecv/WSASend(读写)作为读写检测,将IOCP作为一个通知模型,而"抛弃"它的异步模型。

即:把它当作epoll来用。使得(方便)网络库的设计(譬如socket的读写处理)在windows和linux下实现统一:  底层获得读写通知,应用层(网络库中)自己处理读写。

II:单线程EventLoop

1:EventLoop是一个单线程的网络IO循环,使用一个iocp(epoll)实例,管理多个DataSocket。

通过EventLoop的addConnection接口为它添加DataSocket(并传入一个回调),并会在EventLoop接手它后触发传入的回调函数--处理链接建立之后的业务逻辑。

DataSocket 即为一个客户端连接-会话,用户可以为它设置事件回调函数。

setDataHandle:设置收到消息后的回调函数。

setDisConnectHandle:设置链接断开后的回调函数。

当然我们也可以通过disConnect主动断开会话的网络连接。

2:EventLoop实现线程安全的wakeup和异步消息队列,用于外部逻辑线程投递异步操作(以及唤醒,以让eventloop尽可能更快的处理请求)。

3:std::shared_ptr作为packet类型,用于将同一个packet投递给多个客户端DataSocket(避免分配多个消息),DataSocket 内置一个队列,保存当前pending在它上的待发packet list。

之所以采用std::shared_ptr,是因为它自带引用计数处理,可以方便的应对同一个消息包发送给多个客户端时,消息包的分配和释放问题(即此消息全部发送给它的目的客户端,那么此消息就可以回收),

无需自己再写一套消息包设计了。

注:目前linux下给客户端flush发送网络消息时,采用writev提高效率,但windows上没有找到相关函数(WSASend不满足要求),但可以在某些时候将消息memcpy到一个缓冲区,然后一次性send(以减少send系统调用次数))。

III: 封装EventLoop的TCPServer

1:TCPServer处理Listen逻辑以及为新到的链接分配(通过EventLoop的addConnection接口)一个EventLoop。

2!:可从源码中看到DataSocket的事件回调函数所附带的参数是DataSocket*, 但是 TcpServer回调函数参数中,表示会话标识的类型为:int64 id,而非裸指针。

这是因为TCPServer多被用于多线程设计,此时会话的有效性(避免串话)(以及内存的有效性-野指针问题)需要保证,而裸指针并非安全的。

3:第二点说到TcpServer多用于多线程设计时,具体如下:

在它的回调函数中,我们可以将消息投递到一个逻辑线程的消息队列,并wakeup逻辑线程的EventLoop),当逻辑线程被唤醒后,从消息队列中同步读取消息,然后处理。

而当逻辑线程需要发送消息则使用: TCPServer的send接口,参数是一个int64_t id 表示要发送消息的会话,紧接着是一个Packet,表示消息内容。

当然!:TCPServer的回调函数中可以立即处理,而非投递到别的线程进行协作,这样用起来当然更简单了。

譬如在某些网络服务中,不需要很耗时的处理,而仅仅是IO密集型(比如网关),  那么建议直接在回调函数中进行处理(譬如转发)。

注: 此网络库参考了 muduo:https://github.com/chenshuo/muduo

另外致谢:sniperhw:http://www.cnblogs.com/sniperhw 近几年的指点

网络库代码地址: https://github.com/IronsDu/accumulation-dev/tree/master/cpp_net

目前main.cpp实现的是一个ping pong测试(一个进程内:服务器用TCPServer,用多个客户端线程跑各自的EventLoop)。

从main.cpp也可以看到 单线程EventLoop和TCPServer多线程加消息队列的使用方式。

(VS版本至少 VS2013),Linux下签出整个项目后进入/examples/DNet/DNet目录, (我用的g++ 4.9版本 )再使用命令:

g++ -I./../../../cpp_common -I./../../../common eventloop.cpp datasocket.cpp TCPServer.cpp main.cpp -std=c++0x -lrt

TODO::代码中有一些TODO,表示晦涩或者我不太确定没问题~HOHO

另外我很期待后面要做的广播测试(类似MMO的AOI,多个玩家同时移动,要广播给周围N个玩家)。

目前ping pong测试(客户端和服务器在同一个进程内,编译时不开任何优化)在我的机器(AMD Athlon(tm) 7750 Dual-Core Processor,1.3G Hz, CentOS 6.3):

1:TCPServer使用一个线程,并将收到的消息投递到逻辑线程进行ping pong处理。

100个链接,消息包大小为4K,每秒吞吐为190M/s。

1000个链接,消息包大小为4K,每秒吞吐为135M/s。

10000个链接,消息包大小为4K,每秒吞吐为125M/s。

2:TCPServer使用一个线程,直接在自身的消息回调函数中进行ping pong处理。

100个链接,消息包大小为4K,每秒吞吐为315M/s。

1000个链接,消息包大小为4K,每秒吞吐为190M/s。

10000个链接,消息包大小为4K,每秒吞吐为160M/s。

跨平台网络库(采用C++ 11)的更多相关文章

  1. Unity跨平台C/CPP动态库编译---可靠UDP网络库kcp基于CMake的各平台构建实践

    1.为什么需要动态库 a)提供原生代码(native code)的支持,也叫原生插件,但是我实践的是c/cpp跨平台动态库,这里不具体涉及安卓平台java库和ios平台的objectc库构建. b)某 ...

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

    背景 新的c++11标准出后,c++语法得到了非常多的扩展,比起以往不论什么时候都要灵活和高效,提高了程序编码的效率,为软件开发者节省了不少的时间. 之前我也写过基于ACE的网络server框架,但A ...

  3. 跨平台高效率Lua网络库 ( 同步形式的API ,底层是异步非阻塞)

    Joynet 项目地址:https://github.com/IronsDu/Joynet 介绍 high performance network library for lua, based on  ...

  4. boost.ASIO-可能是下一代C++标准的网络库

    曾几何时,Boost中有一个Socket库,但后来没有了下文,C++社区一直在翘首盼望一个标准网络库的出现,网络上开源的网络库也有不少,例如Apache Portable Runtime就是比较著名的 ...

  5. 如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

    1.前言 关于微信内部正在使用的网络层封装库Mars开源的消息,1个多月前就已满天飞(参见<微信Mars:微信内部正在使用的网络层封装库,即将开源>),不过微信团队没有失约,微信Mars ...

  6. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  7. 开源免费的C/C++网络库(c/c++ sockets library)

    (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boo ...

  8. Linux多线程服务端编程:使用muduo C++网络库

    内容推荐本 书主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread.这 ...

  9. 开源免费的C/C++网络库(c/c++ sockets library)补充

    (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boo ...

随机推荐

  1. Fedora 16设置开机自启动程序与Ubuntu的区别

    Ubuntu设置开机自启动脚本的方法是:修改/etc/init.d/rc.local这个文件,添加需要启动的程序即可,相关函数如下: void SetSysAutoBoot() { ] = {}; ; ...

  2. 杭电ACM减花布条

    这是原题的地址 http://acm.hdu.edu.cn/showproblem.php?pid=2087 Problem Description 一块花布条,里面有些图案,另有一块直接可用的小饰条 ...

  3. unigui MessageDlg方法调用例子

    procedure TfrmEmployee.btnDeleteClick(Sender: TObject);var aBool: Boolean;begin inherited; MessageDl ...

  4. js关闭当前页面(窗口)的几种方式总结

    1. 不带任何提示关闭窗口的js代码 <a href="javascript:window.opener=null;window.open('','_self');window.clo ...

  5. Telnet连接Win7系统被拒绝的原因及解决方法

    有时要与计算机进行远程连接,会用到telnet.win7中telnet默认是没有开启的,所以这时连接会连接失败,其失败提示如下: 正在连接192.168.100.103...无法打开到主机的连接. 在 ...

  6. JVM的内存管理机制

    在做Java开发的时候常用的JVM内存管理有两种,一种是堆内存,一种是栈内存.堆内存主要用来存储程序在运行时创建或实例化的对象与变量,例如:我们通过new MyClass()创建的类MyClass的对 ...

  7. java 对excel操作导入excel数据到数据库

    加入jar包jxl.jar ===================services层掉用工具类==================================== // 导入 public Lis ...

  8. 开机自动播放音乐的vbs

    今天无意间看到了vbs这小玩意,就突发奇想,自学了一下,倒弄出如下的小玩意,大牛勿喷!这个可用做撩妹神技也可以用于提醒自己!使用方法:复制程序到txt文本里面保存,然后改后缀为vbs,丢到C:\Pro ...

  9. Animation Spinner【项目】

    https://github.com/vjpr/healthkick/blob/master/src/win/healthkick/ucSpinnerCogs.xaml 网上的例子,放在UserCon ...

  10. Oracle和plsql developer编码设置

    在使用pl/sql developer时,查询出来中文字段显示乱码,因为数据库的编号格式和pl /sql developer的编码格式不统一造成的. 一.查看和修改oracle数据库字符集 selec ...