高性能 Windows Socket 组件 HPSocket

摘要:
HP Socketv2.1.1是一款高性能WindowsSocket组件,正式发布(源代码和测试用例下载)。HP Socket先前为一个大型通信项目开发了一组通用WindowsSocket TCP底层通信组件。组件通过操作界面和侦听器界面与用户交互。用户实现侦听器接口以将自己注册为组件的侦听器。任何用户都可以使用这些组件,只要它们实现了监听器接口;

高性能 Windows Socket 组件 HP-Socket v2.1.1 正式发布(源代码及测试用例下载)

HP-Socket

  以前为某大型通信项目开发了一套通用 Windows Socket TCP 底层通信组件,组件代号为 HP-Socket。现在把 HP-Socket 的所有代码向大众公开,希望能对大家有所帮助;另外,为了让大家能更方便的学习 HP-Socket,因此精心制作了一个功能测试示例(Test Echo)和一个性能测试示例(Test Echo-PFM),大家可以通过这两个测试示例入手,迅速掌握组件的设计思想和使用方法。HP-Socket 包含服务端组件(IOCP 模型)和客户端组件(Event Select 模型),具备以下重要特点:

----------------------------------------------------------------

通用性

  • 通信组件的唯一职责就是接受和发送字节流,绝对不能参与上层协议解析等工作;
  • 与上层使用者解耦、互不依赖,组件与使用者通过操作接口和监听器接口进行交互,组件实现操作接口为上层提供操作方法;使用者实现监听器接口把自己注册为组件的 Listener,接收组件通知。因此,任何使用者只要实现了监听器接口都可以使用组件;另一方面,甚至可以自己重新写一个实现方式完全不同的组件实现给使用者调用,只要该组件遵从组件的操作接口,这也是 DIP 设计原则的体现。

可用性

  可用性对所有通用组件都是至关重要的,如果太难用还不如自己重头写一个来得方便。因此,组件的操作接口和监听器接口设计得尽量简单易用(通俗来说就是“傻瓜化”),这两个接口的主要方法均不超过 5 个。另外,组件完全封装了所有的底层 Socket 通信,上层应用看不到任何通信细节,不必也不能干预任何通信操作,Socket 连接被抽象为 Connection ID,该参数作为连接标识提供给上层应用识别不同的连接。

高性能

  作为底层的通用组件,性能问题是必须考虑的,绝对不能成为系统的瓶颈。而另一方面,从实际出发,根据客户端组件与服务端组件的性能要求采用不同的 Socket 模型。组件在设计上充分考虑了性能、现实使用情景、可用性和实现复杂性等因素,确保满足性能要求的同时又不会写得太复杂。做出以下两点设计决策:

  • 客户端:在单独线程中实现 Socket 通信交互。这样可以避免与主线程或其他线程相互干扰;I/O 模型选择 Event Select 通信模型。
  • 服务端:采用 Windows 平台效率最高的 IOCP 通信模型;利用缓存池技术,在通信的过程中,通常需要频繁的申请和释放内存缓冲区,建立了动态缓存池, 只有当缓存池中没有可用对象时才创建新对象,而当缓存对象过多时则会压缩缓存池;另外,组件的动态内存通过私有堆(Private Heap)机制分配,避免与 new / malloc 竞争同时又减少内存空洞。

伸缩性

  可以根据实际的使用环境要求设置组件的各项性能参数(如:工作线程的数量、各种缓存池的大小、收发缓冲区的大小、Socket 监听队列的大小、Accep 派发的数目以及心跳检查的间隔等)。

HP-Socket 源码、示例及文档资源:请访问项目主页 ^_*

v2.1.1 更新:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

> Server:
-----------------
1、IServerSocketListener 取消 OnPrepareSocket(connID, socket) 通知方法
2、IServerSocketListener 修改 OnAccept((connID, soClient) 通知方法,增加参数‘soClient’,用于实现原 OnPrepareSocket(connID, socket) 通知方法的功能
3、IServerSocketListener 增加 OnPrepareListen(soListen) 通知方法,用于设置监听 socket 的 SOCKET 选项
4、ISocketServer 增加方法 GetListenAddress(strAddress, usPort),用于获取监听 Socket 的地址信息
5、ISocketServer 增加方法 GetClientAddress(connID, strAddress, usPort),用于某个客户端连接的地址信息
6、优化 Socket 缓存池和内存块缓存池管理
7、调整一些属性访问方法的方法名
8、修复BUG:特殊情形下可能出现死锁现象

> Client:
-----------------
1、ISocketServer 增加方法 GetLocalAddress(strAddress, usPort),用于获取 Client Socket 的地址信息
2、优化数据发送方式,提升数据发送效率

> 其他更新:
-----------------
1、优化 TestEcho 和 TestEcho-PFM 测试程序
3、在 SocketHelper.h (.cpp) 中添加若干帮助函数
4、为 SocketHelper.h 中定义的所有接口、类和方法加入注释

v2.0.1 更新:
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
> Server: 
-----------------
1、IServerSocketListener 增加 OnPrepareSocket(connID, socket) 通知方法用于在使用 socket 前设置 SOCKET 选项或过滤客户端连接
2、ISocketServer 增加方法 Disconnect(connID) 用于主动断开客户端连接
3、增加 IServerSocketListener 的子类 CServerSocketListener,提供默认(空的)通知处理方法

> Client:
-----------------
1、IClientSocketListener 增加 OnPrepareSocket(connID, socket) 通知方法用于在使用 socket 前设置 SOCKET 选项
2、支持异步 Connect:ISocketServer 的 Start() 方法增加一个参数 (BOOL bAsyncConnect) 设置是否采用异步 Connect
3、增加 IClientSocketListener 的子类 CClientSocketListener,提供默认(空的)通知处理方法。
4、修复BUG:超高负载情形下出现丢包现象

> 其它更新:
-----------------
1、支持 Windows x64 平台
2、优化 TestEcho 和 TestEcho-PFM 测试程序 3、TestEcho 客户端程序加入“异步连接”示例 4、TestEcho 服务端程序加入“连接过滤”和“主动断开连接”示例



 原文:《高性能 Windows Socket 服务端与客户端组件(源代码及测试用例下载)

   自从本座发表了两篇关于 Windows Socket 通信组件实现的文章后,收到不少读者的留言,希望能分享完整的源代码。此时,本座不敢弊帚自珍。特意在此提供服务端组件和客户端组件的完整代码。另外,为便于读者学习和理解,花了一点点时间精心制作了两个测试用例,一个用于功能测试(TestEcho),另一个用于性能测试(TestEcho-PFM)。读者可以通过这两个测试用例入手,迅速掌握组件的使用方法。希望对大家有所帮助,谢谢 ~ ^_^ ~

  (轻踩这里,你懂的 ^_*


 原文:《基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现

 设计概述

  服务端通信组件的设计是一项非常严谨的工作,其中性能、伸缩性和稳定性是必须考虑的硬性质量指标,若要把组件设计为通用组件提供给多种已知或未知的上层应用使用,则设计的难度更会大大增加,通用性、可用性和灵活性必须考虑在内。

  现以一个基于 IOCP 的通用异步 Windows Socket TCP 服务端组件为例子,讲述其设计与实现相关的问题,希望能引发大家的思考,对大家日后开展相关类似工作时有所帮助。关于通用性、可用性、Socket 模型选型以及接口模型的设计等问题已经在本座前段时间发表的《通用异步 Windows Socket TCP 客户端组件的设计与实现》中进行过阐述,此处就不再重复了。现在主要针对服务端通信组件的特点阐述设计其设计和实现相关的问题。

   一、线程结构

  与组件相关的线程有 3 种:使用者线程、Accept  线程和工作线程,其中后 2 种由组件实现。

    1. 使用者线程:通过调用 Start/Stop/Send 等组件方法操作组件的一个或多个线程,通常是程序的主线程或其它业务逻辑线程。
    2. Accept 线程:使用 AcceptEx() 接收客户端连接请求并创建 Client Socket 的线程,将其独立出来,实现为单独的线程将使组件的模块划分更清晰,更重要的是避免与业务逻辑和通信处理的相互影响。
    3. 工作线程:使用 GetQueuedCompletionStatus() 监听网络事件并处理网络交互的多个线程,工作线程处理完网络事件后会向上层应用发送 OnAccept/OnSend/OnReceive 等组件通知。工作线程的数量可以根据实际情况之行设置(通常建议为:CPU Core Number * 2 + 2)。

  注意:如果上层应用在接收到 OnAccept/OnSend/OnReceive 这些组件通知时直接进行业务逻辑处理并在其中操作组件,则工作线程也成为了使用者线程。另外,如果要处理的业务逻辑比较耗时,上层应用应该在接收到组件通知后交由其他线程处理。

   二、性能

  组件采用 Windows 平台效率最高的 IOCP Socket 通信模型,因此在通信接口的性能方面是有保证的,这里就不多说了。现在从组件的设计与实现的角度来来阐述性能的优化。组件在代码级别做了很多优化,一些看似多余或繁琐的代码其实都是为了性能服务;组件在设计方面主要采用了 2 中优化策略:缓存池和私有堆。

  1. 缓存池:在通信的过程中,通常需要频繁的申请和释放内存缓冲区(TBufferObj)和 Socket 相关的结构体(TSocketObj),这会大大影响组件的性能,因此,组件为 TBufferObj 和 TSocketObj 建立了动态缓存池, 只有当缓存池中没有可用对象时才创建新对象,而当缓存对象过多时则会压缩缓存池。
  2. 私有堆(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 个。 

  • 最重要的第三个问题:组件的性能如何?

  作为底层的通用组件,性能问题是必须考虑的,绝对不能成为系统的瓶颈。而另一方面,从实际出发,毕竟只是一个客户端组件,它的并发性要求远没有服务端那么高。因此,组件在设计上充分考虑了性能、现实使用情景、可用性和实现复杂性等因素,确保满足性能要求的同时又不会写得太复杂。做出以下两点设计决策:

  1. 在单独线程中实现 Socket 通信交互。这样可以避免与主线程或其他线程相互干扰。
  2. I/O 模型选择 WSAEventSelect。细说一下选择这种 I/O 模型的原因:(各种 I/O 模型的性能比较可以参考:《Windows 网络编程(中文第二版)》第 154 页)
  • 阻塞模型:(不解析,你懂的^_^)
  • 非阻塞模型:(性能太低)
  • WSAAsyncSelect: (两个原因:a、性能太低;b、对于纯 Console 程序还要背负 HWND 实在是伤不起呀!)
  • 重叠 I/O:(有点复杂了)
  • 完成端口:(何必呢?)

FTP文件操作之删除文件
 

FTP文件操作之上传文件

FTP文件操作之下载文件

FTP文件操作之删除文件


上面我已经介绍了利用ftp进行上传跟下载,接下来跟大家分享的是删除ftp服务器上的文件的部分。有了上传,有了下载,那么删除自然也是不能少的。

删除相对于上传跟下载更简单一些,它不需要进行文件的传输,只需向FTP服务器发送一个删除的命令。

 

下面是一个删除功能的完整示例:

复制代码
        /// <summary>
        /// FTP删除文件
        /// </summary>
        /// <param name="ftpPath">ftp文件路径</param>
        /// <param name="userId">ftp用户名</param>
        /// <param name="pwd">ftp密码</param>
        /// <param name="fileName">ftp文件名</param>
        /// <returns></returns>
        public string DeleteFile(string ftpPath,string userId,string pwd, string fileName)
        {
            string sRet = "删除成功!";   
            FtpWebResponse Respose = null;
            FtpWebRequest reqFTP = null;
            Stream localfile = null;
            Stream stream = null;
            try
            {
                //根据uri创建FtpWebRequest对象  
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(string.Format(@"{0}{1}", ftpPath, fileName)));

                //提供账号密码的验证  
                reqFTP.Credentials = new NetworkCredential(userId, pwd);    

                //默认为true是上传完后不会关闭FTP连接  
                reqFTP.KeepAlive = false;    

                //执行删除操作
                reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;

                Respose = (FtpWebResponse)reqFTP.GetResponse();      
            }           
            catch (Exception ex)
            {
                sRet = ex.Message;
            }

            finally
            {
                //关闭连接跟流
                if (Respose != null)
                    Respose.Close();
                if (localfile != null)
                    localfile.Close();
                if (stream != null)
                    stream.Close();
            }

            //返回执行状态
            return sRet;
        }
复制代码

 

不难发现,删除所用的代码比上传跟下载少了很多,这也说明了它比之前的两个功能更简单一些。虽然简单但同样重要,ftp文件的操作一般都会同时出现,配合完成一系列的工作,之后的博客中还会继续更新,敬请关注!

 

 

 
分类: .Net
原文出处:怪兽的博客  怪兽的微博  怪兽乐园Q群
 

免责声明:文章转载自《高性能 Windows Socket 组件 HPSocket》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#批量向数据库插入数据5大移动应用加固平台评测下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

css div上下左右居中

相信大家都会遇到这样的问题,要求一个块上下左右居中,在这里我总结了几个好用的方法 1.已知要居中的块width height  假设  content 要在f里上下左右居中 <div class="f"><div class="content"></div></div> <style> .f{  ...

Ant Design Pro入门教程,安装,运行(V5 Typescript版)

【前言】 找了很多Admin模板,最后还是看中了AntDesignPro这个阿里巴巴开源的Admin框架,长这样(还行吧,目前挺主流的): 官网地址:https://pro.ant.design/index-cn 该套模板是使用了React开发框架作为基础,AntDesign(蚂蚁金服开源UI组件库)作为UI库,集成了Dva,Umi,Mock等库,如果不...

Unity中对注册表进行修改

问题背景: PC端软件开发,当我在Unity中的PlayerSetting中设置好分辨率,每次打包运行后会记忆上次退出时窗口的分辨率(记忆窗口状态),导致下次打开时不是PlayerSetting中的初始设置,而是读取注册表记录的数据。而我的需求时必须每次进去时都是指定的那个分辨率。 问题纠结点: 1.注册表信息是否可删,怎么获取到删除 2.也不能直接删除整...

【初次使用h0遇到的一些问题】

此篇为萌新级别hzero 食用指南,记述了我学习过程中遇到的问题和心得,所记述不一定正确,仅供参考~ PS:有些图很模糊,不晓得为什么从word或者Ty里拿出来的画质压缩得这么厉害,见谅。    1.版本号问题,当前应避免hzero企业版的 1.6.1和1.6.4版本服务组件(但是也不一定,有的人会出现的问题,别的人不一定会出现。很玄学,可能后续兼容性会加...

Spring源码分析:@Configuration原理

1.本文基于spring5.3.x。 环境搭建 bean: public class Cat { } public class Dog { } public class DogFactoryBean implements FactoryBean<Dog> { @Override public Dog getObject() throws...

XNA框架基础——从头开始

从头开始 您已经准备好了一切,现在就让我们开始编码吧!本节您将在XNA Studio模板的帮助下创建一个简单的游戏项目,然后在Update和Draw方法中添加少量代码以实现一些小功能。在下一小节学习了SpriteBatch类之后,您将创建您的第一个游戏。 您的第一个项目 打开XNA Game Studio Express,在菜单栏中选择“文件→新建项目...