- 浏览: 111218 次
- 性别:
- 来自: 昆明
-
文章分类
- 全部博客 (151)
- 120D02 (5)
- 直升机 (1)
- 我的技术资料收集 (82)
- 的技术资料收集 (4)
- .NET Solution (2)
- ASP.NET (1)
- Linq to sql (1)
- 数据库技术(MS SQL) (2)
- 架构/设计 (1)
- 敏捷/持续集成 (1)
- C#.NET开发 (1)
- Matlab开发 (1)
- WinForm开发 (1)
- 开源技术 (1)
- jQuery (1)
- 我的博文 (4)
- js (2)
- android (2)
- 9. 读书笔记 (1)
- CSS3 (1)
- HTML5 (1)
- JavaScript (5)
- 移动开发 (2)
- 编程心得 (1)
- Linux操作系统 (1)
- (BI)商业智能 (1)
- IOS (1)
- Windows Phone (2)
- C# API (1)
- JQuery系列 (1)
- TFS (1)
- C# (2)
- ExtJs (1)
- .NET (1)
- Nginx (1)
- WCF学习笔记 (1)
- Computer Graphic (1)
- IT产品 (1)
- 工具分享 (1)
- MySelf (1)
- C#专栏 (1)
- 管理 (1)
- 基于Oracle Logminer数据同步 (1)
- 日常 (1)
- 实用工具 (1)
- 网页设计 (1)
- avalon (1)
- flash (1)
- DDD (1)
- 01 技术Android (1)
- WCF (1)
- selenium (1)
最新评论
-
464410531:
三国杀。。。。。。。。。。。。。。。。。。。。。。。。。。。。 ...
实用的职场宝典:不提拔你,就因为你只想把工作做好
HP-Socket 是一套通用的高性能 Windows Socket 组件包,包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),广泛适用于 Windows 平台的 TCP 通信系统。HP-Socket 对通信层实现完全封装,上层应用不必关注通信层的任何细节;HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到各类应用程序中;另外,为了让大家能更方便的学习 HP-Socket,特此精心制作了一个功能测试示例(Test Echo)一个性能测试示例(Test Echo-PFM)和一个 PULL 模型测试示例(Test Echo-Pull),用户可以通过这两个测试示例入手,迅速掌握组件的设计思想和使用方法。
----------------------------------------------------------------
通用性
- 通信组件的唯一职责就是接受和发送字节流,绝对不能参与上层协议解析等工作;
- 与上层使用者解耦、互不依赖,组件与使用者通过操作接口和监听器接口进行交互,组件实现操作接口为上层提供操作方法;使用者实现监听器接口把自己注册为组件的 Listener,接收组件通知。因此,任何使用者只要实现了监听器接口都可以使用组件;另一方面,甚至可以自己重新写一个实现方式完全不同的组件实现给使用者调用,只要该组件遵从组件的操作接口,这也是 DIP 设计原则的体现。
可用性
可用性对所有通用组件都是至关重要的,如果太难用还不如自己重头写一个来得方便。因此,组件的操作接口和监听器接口设计得尽量简单易用(通俗来说就是“傻瓜化”),这两个接口的主要方法均不超过 5 个。另外,组件完全封装了所有的底层 Socket 通信,上层应用看不到任何通信细节,不必也不能干预任何通信操作,Socket 连接被抽象为 Connection ID,该参数作为连接标识提供给上层应用识别不同的连接。
高性能
作为底层的通用组件,性能问题是必须考虑的,绝对不能成为系统的瓶颈。而另一方面,从实际出发,根据客户端组件与服务端组件的性能要求采用不同的 Socket 模型。组件在设计上充分考虑了性能、现实使用情景、可用性和实现复杂性等因素,确保满足性能要求的同时又不会写得太复杂。做出以下两点设计决策:
- 客户端:在单独线程中实现 Socket 通信交互。这样可以避免与主线程或其他线程相互干扰;I/O 模型选择 Event Select 通信模型。
- 服务端:采用 Windows 平台效率最高的 IOCP 通信模型;利用缓存池技术,在通信的过程中,通常需要频繁的申请和释放内存缓冲区,建立了动态缓存池, 只有当缓存池中没有可用对象时才创建新对象,而当缓存对象过多时则会压缩缓存池;另外,组件的动态内存通过私有堆(Private Heap)机制分配,避免与 new / malloc 竞争同时又减少内存空洞。
伸缩性
可以根据实际的使用环境要求设置组件的各项性能参数(如:工作线程的数量、各种缓存池的大小、收发缓冲区的大小、Socket 监听队列的大小、Accep 派发的数目以及心跳检查的间隔等)。
(项目主页:http://www.jessma.org,下载地址:http://www.oschina.net/p/hp-socket)
*** v2.2.1 更新 ***
> PULL 模型支持:
-----------------
- ISocketListener 增加 PULL 模型数据接收通知方法 OnReceive(dwConnID, int)
- 增加 PULL Socket 接口 IPullSocket,该接口的 Fetch(dwConnID, pBuffer, iLength) 方法用于抓取通信数据
> Server:
-----------------
- 服务端 Socket 接口 ISocketServer 改名为 IServerSocket
- 增加 PULL Server Socket 监听器抽象类 CPullServerSocketListener
- 增加 PULL Server Socket 接口 IPullServerSocket
- 增加 PULL Server Socket 实现类 CIocpPullServer
> Client:
-----------------
- 客户端 Socket 接口 ISocketClient 改名为 IClientSocket
- 客户端 Socket 实现类 CSocketClient 改名为 CClientSocket
- 增加 PULL Client Socket 监听器抽象类 CPullClientSocketListener
- 增加 PULL Client Socket 接口 IPullClientSocket
- 增加 PULL Client Socket 实现类 CPullClientSocket
> 其它更新:
-----------------
- 增加 PULL Socket 测试程序 TestEcho-Pull
- 在 SocketHelper.h (.cpp) 中添加若干帮助结构体
> 升级说明:
-----------------
- 使用 HP-Socket v2.1.1 的应用程序可以安全升级到 v2.2.1
- 由于 ISocketServer、ISocketClient 和 CSocketClient 的名称已修改,因此,应用程序需要对引用的名称和包含的头文件名作相应修改
*** v2.1.1 更新 ***
> Server:
-----------------
- IServerSocketListener 取消 OnPrepareSocket(connID, socket) 通知方法
- IServerSocketListener 修改 OnAccept((connID, soClient) 通知方法,增加参数‘soClient’,用于实现原 OnPrepareSocket(connID, socket) 通知方法的功能
- IServerSocketListener 增加 OnPrepareListen(soListen) 通知方法,用于设置监听 socket 的 SOCKET 选项
- ISocketServer 增加方法 GetListenAddress(strAddress, usPort),用于获取监听 Socket 的地址信息
- ISocketServer 增加方法 GetClientAddress(connID, strAddress, usPort),用于某个客户端连接的地址信息
- 优化 Socket 缓存池和内存块缓存池管理
- 调整一些属性访问方法的方法名
- 修复BUG:特殊情形下可能出现死锁现象
> Client:
-----------------
- ISocketServer 增加方法 GetLocalAddress(strAddress, usPort),用于获取 Client Socket 的地址信息
- 优化数据发送方式,提升数据发送效率
> 其他更新:
-----------------
- 优化 TestEcho 和 TestEcho-PFM 测试程序
- 在 SocketHelper.h (.cpp) 中添加若干帮助函数
- 为 SocketHelper.h 中定义的所有接口、类和方法加入注释
*** v2.0.1 更新 ***
> Server:
-----------------
- IServerSocketListener 增加 OnPrepareSocket(connID, socket) 通知方法用于在使用 socket 前设置 SOCKET 选项或过滤客户端连接
- ISocketServer 增加方法 Disconnect(connID) 用于主动断开客户端连接
- 增加 IServerSocketListener 的子类 CServerSocketListener,提供默认(空的)通知处理方法
> Client:
-----------------
- IClientSocketListener 增加 OnPrepareSocket(connID, socket) 通知方法用于在使用 socket 前设置 SOCKET 选项
- 支持异步 Connect:ISocketServer 的 Start() 方法增加一个参数 (BOOL bAsyncConnect) 设置是否采用异步 Connect
- 增加 IClientSocketListener 的子类 CClientSocketListener,提供默认(空的)通知处理方法。
- 修复BUG:超高负载情形下出现丢包现象
> 其他更新:
-----------------
- 支持 Windows x64 平台
- 优化 TestEcho 和 TestEcho-PFM 测试程序
- TestEcho 客户端程序加入“异步连接”示例
- TestEcho 服务端程序加入“连接过滤”和“主动断开连接”示例
相关博文:《高性能 Windows Socket 服务端与客户端组件(源代码及测试用例下载)》
自从本座发表了两篇关于 Windows Socket 通信组件实现的文章后,收到不少读者的留言,希望能分享完整的源代码。此时,本座不敢弊帚自珍。特意在此提供服务端组件和客户端组件的完整代码。另外,为便于读者学习和理解,花了一点点时间精心制作了两个测试用例,一个用于功能测试(TestEcho),另一个用于性能测试(TestEcho-PFM)。读者可以通过这两个测试用例入手,迅速掌握组件的使用方法。希望对大家有所帮助,谢谢 ~ ^_^ ~
相关博文:《基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现》
设计概述
服务端通信组件的设计是一项非常严谨的工作,其中性能、伸缩性和稳定性是必须考虑的硬性质量指标,若要把组件设计为通用组件提供给多种已知或未知的上层应用使用,则设计的难度更会大大增加,通用性、可用性和灵活性必须考虑在内。
现以一个基于 IOCP 的通用异步 Windows Socket TCP 服务端组件为例子,讲述其设计与实现相关的问题,希望能引发大家的思考,对大家日后开展相关类似工作时有所帮助。关于通用性、可用性、Socket 模型选型以及接口模型的设计等问题已经在本座前段时间发表的《通用异步 Windows Socket TCP 客户端组件的设计与实现》中进行过阐述,此处就不再重复了。现在主要针对服务端通信组件的特点阐述设计其设计和实现相关的问题。
一、线程结构
与组件相关的线程有 3 种:使用者线程、Accept 线程和工作线程,其中后 2 种由组件实现。
- 使用者线程:通过调用 Start/Stop/Send 等组件方法操作组件的一个或多个线程,通常是程序的主线程或其它业务逻辑线程。
- Accept 线程:使用 AcceptEx() 接收客户端连接请求并创建 Client Socket 的线程,将其独立出来,实现为单独的线程将使组件的模块划分更清晰,更重要的是避免与业务逻辑和通信处理的相互影响。
- 工作线程:使用 GetQueuedCompletionStatus() 监听网络事件并处理网络交互的多个线程,工作线程处理完网络事件后会向上层应用发送 OnAccept/OnSend/OnReceive 等组件通知。工作线程的数量可以根据实际情况之行设置(通常建议为:CPU Core Number * 2 + 2)。
注意:如果上层应用在接收到 OnAccept/OnSend/OnReceive 这些组件通知时直接进行业务逻辑处理并在其中操作组件,则工作线程也成为了使用者线程。另外,如果要处理的业务逻辑比较耗时,上层应用应该在接收到组件通知后交由其他线程处理。
二、性能
组件采用 Windows 平台效率最高的 IOCP Socket 通信模型,因此在通信接口的性能方面是有保证的,这里就不多说了。现在从组件的设计与实现的角度来来阐述性能的优化。组件在代码级别做了很多优化,一些看似多余或繁琐的代码其实都是为了性能服务;组件在设计方面主要采用了 2 中优化策略:缓存池和私有堆。
- 缓存池:在通信的过程中,通常需要频繁的申请和释放内存缓冲区(TBufferObj)和 Socket 相关的结构体(TSocketObj),这会大大影响组件的性能,因此,组件为 TBufferObj 和 TSocketObj 建立了动态缓存池, 只有当缓存池中没有可用对象时才创建新对象,而当缓存对象过多时则会压缩缓存池。
- 私有堆(Private Heap):在操作系统中,new / malloc 等操作是串行化的,虽然一般的应用程序不用太在乎这个问题,但是在一个高并发的服务器中则是个不可忽略的问题,另外 TBufferObj 和 TSocketObj 均为大小固定的结构体,因此非常适合在私有堆中分配内存,避免与 new / malloc 竞争同时又减少内存空洞。(关于私有堆的使用方法请参考这里 ^_^)
三、通用性与可用性
与《通用异步 Windows Socket TCP 客户端组件的设计与实现》描述的客户端接口一样,服务端组件也提供了两组接口:ISocketServer 接口提供组件操作方法,由上层应用直接调用;IServerSocketListener 接口提供组件通知方法,由上层应用实现,这两个接口设计得非常简单,主要方法均不超过 5 个。由于组件自身功能完备(不需要附带其它库或代码)并且职责单一(只管通信,不参与业务逻辑),因此可以十分方便第整合到任何类型的应用程序中。
四、伸缩性
可以根据实际的使用环境要求设置工作线程的数量、 TBufferObj 和 TSocketObj 缓存池的大小、TBufferObj 缓冲区的大小、Socket 监听队列的大小、AccepEx 派发的数目以及心跳检查的间隔等。
五、连接标识
组件完全封装了所有的底层 Socket 通信,上层应用看不到任何通信细节,不必也不能干预任何通信操作。另外,组件在 IServerSocketListener 通知接口的所有方法中都有一个 Connection ID 参数,该参数作为连接标识提供给上层应用识别不同的连接。
相关博文:《通用异步 Windows Socket TCP 客户端组件的设计与实现》
设计概述
编写 Windows Socket TCP 客户端其实并不困难,Windows 提供了6种 I/O 通信模型供大家选择。但本座看过很多客户端程序都把 Socket 通信和业务逻辑混在一起,剪不断理还乱。每个程序都 Copy / Parse 类似的代码再进行修改,实在有点情何以堪。因此本座利用一些闲暇时光写了一个基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件和一个通用异步 Windows Socket TCP 客户端组件供各位看官参详参详,希望能激发下大家的灵感。本篇文章讲述客户端组件。闲话少说,我们现在步入正题。
- 最重要的第一个问题:如何才能达到通用?
答:很简单。
1、限制组件的职能,说白了,通信组件的唯一职责就是接受和发送字节流,绝对不能参与上层协议解析等工作。不在其位不谋其政就是这个意思。
2、与上层使用者解耦、互不依赖,组件与使用者通过接口方法进行交互,组件实现 ISocketClient 接口为上层提供操作方法;使用者通过 IClientSocketListener 接口把自己注册为组件的 Listener,接收组件通知。因此,任何使用者只要实现了 IClientSocketListener 接口都可以使用组件;另一方面,你甚至可以自己重新写一个实现方式完全不同的组件实现给使用者调用,只要该组件遵从 ISocketClient 接口。这也是 DIP 设计原则的体现(若想了解更多关于设计原则的内容请猛击这里 ^_^)。
- 最重要的第二个问题:可用性如何,也就是说使用起来是否是否方便?
答:这个问题问得很好,可用性对所有通用组件都是至关重要的,如果太难用还不如自己重头写一个来得方便。因此,ISocketClient 和 IClientSocketListener 接口设计得尽量简单易用(通俗来说就是“傻瓜化”),这两个接口的主要方法均不超过 5 个。
- 最重要的第三个问题:组件的性能如何?
作为底层的通用组件,性能问题是必须考虑的,绝对不能成为系统的瓶颈。而另一方面,从实际出发,毕竟只是一个客户端组件,它的并发性要求远没有服务端那么高。因此,组件在设计上充分考虑了性能、现实使用情景、可用性和实现复杂性等因素,确保满足性能要求的同时又不会写得太复杂。做出以下两点设计决策:
- 在单独线程中实现 Socket 通信交互。这样可以避免与主线程或其他线程相互干扰。
- I/O 模型选择 WSAEventSelect。细说一下选择这种 I/O 模型的原因:(各种 I/O 模型的性能比较可以参考:《Windows 网络编程(中文第二版)》第 154 页)
- 阻塞模型:(不解析,你懂的^_^)
- 非阻塞模型:(性能太低)
- WSAAsyncSelect: (两个原因:a、性能太低;b、对于纯 Console 程序还要背负 HWND 实在是伤不起呀!)
- 重叠 I/O:(有点复杂了)
- 完成端口:(何必呢?)
发表评论
-
Javascript:猜猜弹出的是啥?为啥? - 幸福框架
2013-06-28 13:33 447原帖地址:http://www.cnblogs.com/hap ... -
C#中WindowsForm常见控件的运用 -- - 李晓峰
2013-06-28 13:27 1766原帖地址:http://www.cnblogs.com/liy ... -
海量数据处理利器之Hash——在线邮件地址过滤 - MyDetail
2013-06-27 12:00 672原帖地址:http://www.cnblo ... -
ASP.NET MVC 4 for Visual Studio 2010 下载地址 - 张鸿伟
2013-06-27 11:48 764原帖地址:http://www.cnblogs.com/wei ... -
【ASP.NET Web API教程】6.2 ASP.NET Web API中的JSON和XML序列化 - r01cn
2013-06-26 11:00 927原帖地址:http://www.cnblogs.com/r01 ... -
[珠玑之椟]估算的应用与Little定律 - 五岳
2013-06-26 10:54 651原帖地址:http://www.cnblogs.com/wuy ... -
30行,金额转人民币大写的代码 - 史蒂芬.王
2013-06-26 10:42 1038原帖地址:http://www.cnblogs.com/ste ... -
从银行的钱荒看一个公司的团队建设 产品线过多最终导致最赚钱的项目面临破产 - James Li
2013-06-26 10:36 646原帖地址:http://www.cnblogs.com/Jam ... -
Windows 8 动手实验系列教程 实验6:设置和首选项 - zigzagPath
2013-06-25 13:39 553原帖地址:http://www.cnblogs.com/zig ... -
闲聊可穿戴设备 - shawn.xie
2013-06-25 13:33 628原帖地址:http://www.cnblo ... -
如何使用开源库,吐在VS2013发布之前,顺便介绍下VS2013的新特性"Bootstrap" - 量子计算机
2013-06-25 13:27 883原帖地址:http://www.cnblogs.com/DSh ... -
一步一步将自己的代码转换为观察者模式 - 文酱
2013-06-23 11:36 630原帖地址:http://www.cnblo ... -
iOS内存错误EXC_BAD_ACCESS的解决方法(message sent to deallocated instance) - VicStudio
2013-06-23 11:30 560原帖地址:http://www.cnblogs.com/vic ... -
记录asp.net在IE10下事件丢失排错经过 - Adming
2013-06-23 11:24 727原帖地址:http://www.cnblogs.com/wea ... -
记 FineUI 官方论坛所遭受的一次真实网络攻击!做一个像 ice 有道德的黑客! - 三生石上
2013-06-23 11:18 812原帖地址:http://www.cnblogs.com/san ... -
3、使用Oracle Logminer同步Demo
2013-06-19 10:33 583原帖地址:http://www.cnblogs.com/shi ... -
算法实践——数独的基本解法
2013-06-19 10:27 1468原帖地址:http://www.cnblogs.com/gre ... -
简单实现TCP下的大文件高效传输
2013-06-19 10:21 705原帖地址:http://www.cnblogs.com/sma ... -
avalon - 初步接触
2013-06-18 10:06 796原帖地址:http://www.cnblogs.com/aar ... -
Nginx学习笔记(一) Nginx架构
2013-06-18 09:59 543原帖地址:http://www.cnblogs.com/cod ...
相关推荐
harbor-offline-installer-v2.2.1,2021-4-21 20:53:23
RCS-2000(v2.2.1)操作手册.pdf RCS-2000(v2.2.1)操作手册.pdf是海康RCS的一份操作手册,旨在指导用户正确使用RCS-2000调度控制系统V2.2.1版本。该手册涵盖了系统配置、服务配置、地图管理、任务管理、设备管理、...
如果VMware ESXi安装盘未能识别你的服务器网卡或者RAID卡,就需要自定义ESXi安装盘,需要...ESXi5-CPT-v2.2.1 ESXi-Customizer-v2.7.2 使用方法请百度“ESXi 硬件驱动支持终极解决之道”。
**Qt5 VS2017 插件:qt-vsaddin-msvc2017-2.2.1.vsix** 本文将深入探讨标题所提及的“qt-vsaddin-msvc2017-2.2.1.vsix”插件,它是专为Visual Studio 2017设计的Qt开发工具,旨在提升Qt应用在Visual Studio环境下的...
qt-creator-win-opensource-2.2.1
QtScrcpy-mac-x64-v2.2.1.dmg
qt-creator-win-opensource-2.2.1
harbor-offline-installer-v2.2.1
多商户商家入驻功能 CRMEB_Mer_v2.2.1(20230918) 1、新增付费会员 2、新增社区发布短视频 3、新增商品参数 4、新增多件商品多次核销功能 5、新增取消退货退款申请 6、新增支付宝支付充值余额 7、新增城市数据,...
hyperledger-fabric-readthedocs-io-en-v2.2.1
《Hyperledger Fabric 2.2.1:构建分布式账本技术的基石》 Hyperledger Fabric是Linux基金会主导的开源项目,旨在为企业级区块链提供坚实的基础。这个名为"hyperledger-fabric-linux-amd64-2.2.1.tar.gz"的压缩包...
《Unity3D反作弊工具包 Anti-Cheat Toolkit v2.2.1详解》 在游戏开发领域,尤其是多人在线竞技游戏中,反作弊机制是至关重要的。Unity3D作为一款广泛使用的游戏引擎,提供了多种工具来帮助开发者对抗作弊行为。本文...
mysql-mmm-agent-2.2.1-2.el6.noarch.rpm mysql-mmm-agent-2.2.1-2.el6.noarch.rpm
在实际开发中,Struts2-Spring-Plugin-2.2.1.jar的使用极大地提高了开发效率,降低了组件间的耦合度,使得整个应用更加灵活且易于维护。为了更好地利用这个插件,开发者需要对Struts2和Spring框架有深入的理解,同时...
Struts2-dojo-plugin-2.2.1.jar 是一个针对Apache Struts2框架的扩展插件,主要用于增强Struts2应用的用户界面交互性,特别是通过集成Dojo JavaScript库来提供丰富的AJAX功能和用户体验。这个插件是Struts2与Dojo ...
"kekingcn-file-online-preview-v2.2.1" 是一个专用于在线文件预览的软件包,版本号为2.2.1,其主要功能是提供对PDF文档的便捷预览服务。这个软件包以ZIP格式压缩,方便用户下载和安装。在解压后,我们可以看到一个...
版本v2.2.1可能包含了一些性能优化、新功能和对之前版本的bug修复。开发者可以利用这个库轻松地实现STM32与USB设备之间的交互,如连接存储设备、打印机、摄像头等。 库中的关键组件包括: 1. **主机控制器驱动**:...
Wireshark-win64-2.2.1.exe,自己留存