一个对Winsock完成端口模型封装的…

Winsock 完成端口模型封装的全新类 在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock 完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有一定的了解。如果不了解,推荐几本书:《Inside Windows 2000,《WINDOWS核心编程》,《WIN32多线程程序设计》、《WINDOWS网络编程技术》。在去年,我在C语言下用完成端口模型写了一个WEBSERVER,前些天,我决定用C++重写这个WEBSERVER,给这个WEBSERVER增加了一些功能,并改进完成端口操作方法,比如采用AcceptEx来代替accept和使用LOOKASIDE LIST来管理内存,使得WEBSERVER的性能有了比较大的提高。 (under the Windows network server program development, no doubt, Winsock completed port model is the most efficient. Winsock port model with complete preview of overlap and complete port IO to achieve complete port after the model to understand is a relatively simple, but want to know the complete Winsock port model, the need for the Windows threads, thread synchronization, Winsock API and Windows IO mechanism of a certain understanding. If we do not understand, recommended several books : "Inside Windows 2000," Windows core programming "," WIN32 multithreaded programming "," WINDOWS network programming technology. " Last year, I used C language under complete port model was a WEBSERVER, few days ago, I decided to rewrite the C WEBSERVER to the WEBSERVER i) 立即下载

在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock 完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有一定的了解。如果不了解,推荐几本书:《Inside Windows 2000,《WINDOWS核心编程》,《WIN32多线程程序设计》、《WINDOWS网络编程技术》。在去年,我在C语言下用完成端口模型写了一个WEBSERVER,前些天,我决定用C++重写这个WEBSERVER,给这个WEBSERVER增加了一些功能,并改进完成端口操作方法,比如采用AcceptEx来代替accept和使用LOOKASIDE LIST来管理内存,使得WEBSERVER的性能有了比较大的提高。
  
  在重写的开始,我决定把完成端口模型封装成一个比较通用的C++类,针对各种网络服务端程序的开发,只要简单地继承这个类,改写其中两个虚拟函数就能满足各种需要。到昨天为止,WEBSERVER重写完毕,我就写了这篇文章对完成端口模型做一个总结,并介绍一下我的这个类。
  
  一:完成端口模型
  
  至于完成端口和Winsock完成端口模型的详细介绍,请参见我上面介绍的那几本书,这里只是我个人对完成端口模型理解的一点心得。
  
  首先我们要抽象出一个完成端口大概的处理流程:
  
  1:创建一个完成端口。
  
  2:创建一个线程A。
  
  3:A线程循环调用GetQueuedCompletionStatus()函数来得到IO操作结果,这个函数是个阻塞函数。
  
  4:主线程循环里调用accept等待客户端连接上来。
  
  5:主线程里accept返回新连接建立以后,把这个新的套接字句柄用CreateIoCompletionPort关联到完成端口,然后发出一个异步的WSASend或者WSARecv调用,因为是异步函数,WSASend/WSARecv会马上返回,实际的发送或者接收数据的操作由WINDOWS系统去做。
  
  6:主线程继续下一次循环,阻塞在accept这里等待客户端连接。
  
  7:WINDOWS系统完成WSASend或者WSArecv的操作,把结果发到完成端口。

8:A线程里的GetQueuedCompletionStatus()马上返回,并从完成端口取得刚完成的WSASend/WSARecv的结果。
  
  9:在A线程里对这些数据进行处理(如果处理过程很耗时,需要新开线程处理),然后接着发出WSASend/WSARecv,并继续下一次循环阻塞在GetQueuedCompletionStatus()这里。
  
  具体的流程请看附图,其中红线表示是WINDOWS系统进行的处理,不需要我们程序干预。

 

一个对Winsock完成端口模型封装的类


    归根到底概括完成端口模型一句话:
  
  我们不停地发出异步的WSASend/WSARecv IO操作,具体的IO处理过程由WINDOWS系统完成,WINDOWS系统完成实际的IO处理后,把结果送到完成端口上(如果有多个IO都完成了,那么就在完成端口那里排成一个队列)。我们在另外一个线程里从完成端口不断地取出IO操作结果,然后根据需要再发出WSASend/WSARecv IO操作。

 

二:提高完成端口效率的几种有效方法
  
  1:使用AcceptEx代替accept。AcceptEx函数是微软的Winsosk 扩展函数,这个函数和accept的区别就是:accept是阻塞的,一直要到有客户端连接上来后accept才返回,而AcceptEx是异步的,直接就返回了,所以我们利用AcceptEx可以发出多个AcceptEx调用
  
  等待客户端连接。另外,如果我们可以预见到客户端一连接上来后就会发送数据(比如WEBSERVER的客户端浏览器),那么可以随着AcceptEx投递一个BUFFER进去,这样连接一建立成功,就可以接收客户端发出的数据到BUFFER里,这样使用的话,一次AcceptEx调用相当于accpet和recv的一次连续调用。同时,微软的几个扩展函数针对操作系统优化过,效率优于WINSOCK 的标准API函数。
  
  2:在套接字上使用SO_RCVBUF和SO_SNDBUF选项来关闭系统缓冲区。这个方法见仁见智,详细的介绍可以参考《WINDOWS核心编程》第9章。这里不做详细介绍,我封装的类中也没有使用这个方法。
  
  3:内存分配方法。因为每次为一个新建立的套接字都要动态分配一个“单IO数据”和“单句柄数据”的数据结构,然后在套接字关闭的时候释放,这样如果有成千上万个客户频繁连接时候,会使得程序很多开销花费在内存分配和释放上。这里我们可以使用lookaside list。开始在微软的platform sdk里的SAMPLE里看到lookaside list,我一点不明白,MSDN里有没有。后来还是在DDK的文档中找到了,,
  
  lookaside list
  
  A system-managed queue from which entries of a fixed size can be allocated and into which entries can be deallocated dynamically. Callers of the Ex(ecutive) Support lookaside list routines can use a lookaside list to manage any dynamically sized set of fixed-size buffers or structures with caller-determined contents.
  
  For example, the I/O Manager uses a lookaside for fast allocation and deallocation of IRPs and MDLs. As another example, some of the system-supplied SCSI class drivers use lookaside lists to allocate and release memory for SRBs.

 

lookaside list名字比较古怪(也许是我孤陋寡闻,第一次看到),其实就是一种内存管理方法,和内存池使用方法类似。我个人的理解:就是一个单链表。每次要分配内存前,先查看这个链表是否为空,如果不为空,就从这个链表中解下一个结点,则不需要新分配。如果为空,再动态分配。使用完成后,把这个数据结构不释放,而是把它插入到链表中去,以便下一次使用。这样相比效率就高了很多。在我的程序中,我就使用了这种单链表来管理。
  
  在我们使用AcceptEx并随着AcceptEx投递一个BUFFER后会带来一个副作用:比如某个客户端只执行一个connect操作,并不执行send操作,那么AcceptEx这个请求不会完成,相应的,我们用GetQueuedCompletionStatus在完成端口中得不到操作结果,这样,如果有很多个这样的连接,对程序性能会造成巨大的影响,我们需要用一种方法来定时检测,当某个连接已经建立并且连接时间超过我们规定的时间而且没有收发过数据,那么我们就把它关闭。检测连接时间可以用SO_CONNECT_TIME来调用getsockopt得到。
  
  还有一个值得注意的地方:就是我们不能一下子发出很多AcceptEx调用等待客户连接,这样对程序的性能有影响,同时,在我们发出的AcceptEx调用耗尽的时候需要新增加AcceptEx调用,我们可以把FD_ACCEPT事件和一个EVENT关联起来,然后用WaitForSingleObject等待这个Event,当已经发出AccpetEx调用数目耗尽而又有新的客户端需要连接上来,FD_ACCEPT事件将被触发,EVENT变为已传信状态,

  WaitForSingleObject返回,我们就重新发出足够的AcceptEx调用。
  
  关于完成端口模型就介绍到这里。下面介绍我封装的类,这个类写完后,我用这个类做了个ECHOSERVER。

  void main()

  {

  CompletionPortModel p;

  p.Init();

 

p.AllocEventMessage();

  if (FALSE == p.PostAcceptEx())

  {

  return;

  }

  p.ThreadLoop();

  return;

  }

  我在我自己的机器上测试,

  客户端的代码是

  for (int i=0; i<10000; i++)

  {

  SOCKET s = socket(….);

  connect(….);

  send(…);

 

recv(…..)

  cout << buffer << endl;

  }

  结果客户端程序在循环到3000多次的时候死掉,但是服务端程序运行良好,重新启动客户端程序,发送接收数据正常。
  
  使用的时候,只需要从这个类派生一个子类,并改写HandleData和DataAction这两个虚函数,对于那些需要连续发送相关联的数据应用(比如传送文件),使用者需要自己扩展这两个函数,比如创建一个全局队列,每次从完成端口里得到数据后插入队列,然后用另外一个线程专门处理这个队列。。。
  
  从结果来看,这个类还有不少需要改进的地方,比如没考虑多处理器上运行的情况。没有考虑完成端口线程阻塞情况,如果考虑完成端口阻塞情况,那么应该创建CPU数据*2个完成端口线程等等,,因为我同时正在做的毕业设计NDIS驱动防火墙开发正在一个比较难的地方卡住了,时间和精力有限,就没有对这个类进行进一步完善,程序中也许有不合理和错误的地方,请高手多多指教。对于高性能的服务端程序开发是比较难的,记得有次和腾讯一个技术人员聊天,他说,像腾讯QQ的开发,难点不在客户端,而在服务端各个服务器之间的通信和同步。服务端程程序的集群和负载平衡是一个很复杂的问题,我在这方面刚接触,希望能有更多的高手出来共享自己的经验。
  
  封装这个类的时候,我把最新的PLATFORM SDK里的例子看了一遍,借鉴了其中很多思路和方法,在此对写这个例子的微软程序员表示感谢:)
  
  类的详细代码可以[点这里]下载
  
  DEMO就是一个ECHOSERVER,记得使用Release模式编译。

 

从这里转的 http://www.qqread.com/vc/c120575020_6.html

Labview程序框架介绍 当掌握LabVIEW基础知识并达到,理解单个小型模块程序会相对轻松。而若想进一步探索大型程序,就必然需要了解程序框架相关内容。LabVIEW常用的程序架构包括等。在多年工作中,我接触过的众多高级工程师所开发的大型程序,基本都基于这些架构搭建。接下来,将为大家详细介绍这些框架。 阅读详情

相关推荐

汽车电子电气架构

控制器:从多独立 ECU → 域控制器(DCU) → 中央计算平台 + 区域控制器,硬件集成度持续提升,冗余减少;算力:从分散无集中算力 → 按域分配算力 → 全域算力集中,算力量级从 MIPS 跃升至 TOPS,支撑高阶智驾;网络:从低速 CAN/LIN 独占 → 以太网为主、总线为辅 → 高速以太网主干,数据传输速率提升千倍;软硬件:从软硬件深度绑定 → 初步解耦 → 完全解耦(SOA),实现 “硬件预埋、软件解锁”;线束。

LXY_LXY_的博客 1437

一个对Winsock 完成端口模型封装的类

2009-03-28 14:02源代码说明: 在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock 完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握 Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有

xumaojun的专栏 618

解锁SPWM电压利用率:三次谐波注入幅值的黄金分割点

本文深入探讨了SPWM电压利用率的提升方法,重点介绍了三次谐波注入技术及其黄金分割点(1/6比例)。通过数学推导和工程实践,揭示了如何通过特定幅值的三次谐波注入将电压利用率从86.6%提升至115%,与SVPWM相当。文章还提供了实验室调试流程和DSP实现代码,帮助工程师优化逆变器设计。

weixin_30729609的博客 916

一个对Winsock完成端口模型封装的类

一个对Winsock完成端口模型封装的类 - 文章来源:中国电脑教育报 作者:elssann   在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock 完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握 Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Win...

Alterhz 173

pgpool-II踩坑日记两则

最近结合pgpool-II进行postgreSQL高可用的部署,过程非常煎熬,作为新手,公司也没有前辈熟悉postgreSQL,只能自己摸索。好在已经搞明白了,把困扰我很长时间的两个问题分享一下。 1. show pool_nodes 第一个问题就是 show pool_nodes 的使用,照着教程建好后,在哪里执行这个指令呢?我在pg服务器上怎么执行这个指令都显示 ERROR: unrecognized configuration parameter "pool_nodes",一度怀疑人生。翻阅了很多资料

zhaizhai6_6的博客 4540

别让PEX和后仿真拖后腿:Calibre与Virtuoso ADE联调的那些‘坑’与最佳实践

本文深入探讨了Calibre与Virtuoso ADE在PEX寄生参数提取和后仿真联调中的常见问题与解决方案。针对DRC/LVS验证通过后出现的网表导入错误和仿真波形异常,提供了七大典型场景的实战经验,包括PEX提取模式选择、CalibreView生成细节、环境变量配置等关键环节的最佳实践,助力工程师高效完成芯片设计验证。

weixin_33695450的博客 393

【转】一个对Winsock 完成端口模型封装的类

文章标题:一个对Winsock 完成端口模型封装的类原 作 者:不详原 出 处:不详发 布 者:loose_went发布类型:转载发布日期:2004-08-16 源代码说明:  在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock 完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口

Gary's Blog --- A C++ programmer 1294

YOLOv12改进策略【Neck】| CGA Fusion:内容引导的注意力融合模块,空间权重引导的多模态特征自适应融合

本文记录的是利用CGA Fusion 模块改进 YOLOv12 的多模态融合部分。(Content-Guided Attention Fusion)通过内容引导注意力生成空间权重,引导高低层特征的自适应融合。本文利用模块,通过内容引导注意力生成空间权重,自适应地融合两个模态的特征,在特征融合阶段实现跨模态语义对齐与噪声抑制,增强对不同模态互补特征的利用能力,从而提升模型在多模态场景下的检测鲁棒性与准确性。DEA-Net: Single image dehazing based on detail-enhan

Limiiiing的博客 434
上一篇: 在VB&nbsp;中调用动态连接库
下一篇: HTML标记大全
龍城狂霸拽爺
博客等级 码龄16年 10粉丝 101原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值