- 浏览: 2036390 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (651)
- ACE (35)
- BAT (9)
- C/C++ (116)
- fast-cgi (14)
- COM (27)
- python (59)
- CGI (4)
- C# (2)
- VC (84)
- DataBase (29)
- Linux (96)
- P2P (6)
- PHP (15)
- Web (6)
- Memcached (7)
- IME输入法 (11)
- 设计模式 (2)
- 搜索引擎 (1)
- 个人情感 (4)
- 笔试/面试 (3)
- 一亩三分地 (33)
- 历史 (2)
- 地理 (1)
- 人物 (3)
- 经济 (0)
- 不仅仅是笑哦 (43)
- 小故事大道理 (2)
- http://www.bjdsmyysjk120.com/ (0)
- http://www.bjdsmyy120.com/ (0)
- 它山之石可以攻玉 (15)
- 大学生你关注些什么 (28)
- 数据恢复 (1)
最新评论
-
luokaichuang:
这个规范里还是没有让我明白当浏览器上传文件时,STDIN的消息 ...
FastCGI规范 -
effort_fan:
好文章!学习了,谢谢分享!
com技术简介 -
vcell:
有错误os.walk(strPath)返回的已经是全部的文件和 ...
通过python获取目录的大小 -
feifeigd:
feifeigd 写道注意:文章中的CPP示例第二行 #inc ...
ATL入门:利用ATL编写简单的COM组件 -
feifeigd:
注意:文章中的CPP示例第二行 #include " ...
ATL入门:利用ATL编写简单的COM组件
在WINDOWS下进行网络服务端程序开发,毫无疑问,Winsock完成端口模型是最高效的。Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,WinsockAPI以及WINDOWSIO机制有一定的了解。如果不了解,推荐几本书:《InsideWindows2000,《WINDOWS核心编程》,《WIN32多线程程序设计》、《WINDOWS网络编程技术》。在去年,我在C语言下用完成端口模型写了一个WEBSERVER,前些天,我决定用C++重写这个WEBSERVER,给这个WEBSERVER增加了一些功能,并改进完成端口操作方法,比如采用AcceptEx来代替accept和使用LOOKASIDELIST来管理内存,使得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系统进行的处理,不需要我们程序干预。
归根到底概括完成端口模型一句话:
我们不停地发出异步的WSASend/WSARecvIO操作,具体的IO处理过程由WINDOWS系统完成,WINDOWS系统完成实际的IO处理后,把结果送到完成端口上(如果有多个IO都完成了,那么就在完成端口那里排成一个队列)。我们在另外一个线程里从完成端口不断地取出IO操作结果,然后根据需要再发出WSASend/WSARecvIO操作。
二:提高完成端口效率的几种有效方法
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数据”和“单句柄数据”的数据结构,然后在套接字关闭的时候释放,这样如果有成千上万个客户频繁连接时候,会使得程序很多开销花费在内存分配和释放上。这里我们可以使用lookasidelist。开始在微软的platformsdk里的SAMPLE里看到lookasidelist,我一点不明白,MSDN里有没有。后来还是在DDK的文档中找到了,,
lookasidelist
Asystem-managedqueuefromwhichentriesofafixedsizecanbeallocatedandintowhichentriescanbedeallocateddynamically.CallersoftheEx(ecutive)Supportlookasidelistroutinescanusealookasidelisttomanageanydynamicallysizedsetoffixed-sizebuffersorstructureswithcaller-determinedcontents.
Forexample,theI/OManagerusesalookasideforfastallocationanddeallocationofIRPsandMDLs.Asanotherexample,someofthesystem-suppliedSCSIclassdriversuselookasideliststoallocateandreleasememoryforSRBs.
lookasidelist
名字比较古怪(也许是我孤陋寡闻,第一次看到),其实就是一种内存管理方法,和内存池使用方法类似。我个人的理解:就是一个单链表。每次要分配内存前,先查看这个链表是否为空,如果不为空,就从这个链表中解下一个结点,则不需要新分配。如果为空,再动态分配。使用完成后,把这个数据结构不释放,而是把它插入到链表中去,以便下一次使用。这样相比效率就高了很多。在我的程序中,我就使用了这种单链表来管理。
在我们使用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。
发表评论
-
__declspec(novtable) 的用法
2010-11-27 14:37 1592__declspec(novtable) 的用法 __d ... -
解决URLDownloadToFile缓存问题的两种方法
2010-09-09 15:18 2926解决URLDownloadToFile缓存问题的两种方法 ... -
修改richedit背景
2010-07-19 22:52 1653RichEditCtrl::SetBackgroundCo ... -
使用ADO封装类的数据库程序开发实例(下)
2010-07-12 15:30 1482使用ADO封装类的数据库 ... -
使用ADO封装类的数据库程序开发实例(上)
2010-07-12 15:28 1219使用ADO封装类的数据库 ... -
VC防止窗口和控件闪烁的方法
2010-07-09 21:16 20301、将Invalidate()替换为Invalidate ... -
防止窗口闪烁地办法
2010-07-09 21:13 1519防止窗口闪烁地办法 也许我们都碰到过这种情况,当你 ... -
使用ADO _ConnectionPtr
2010-07-06 16:04 5273// GetUser.cpp : Defines the ... -
VC用ADO访问数据库全攻略
2010-07-06 15:29 1805VC用ADO访问数据库全 ... -
深入GetMessage和PeekMessage (引自-MSDN技术组)
2010-06-10 16:59 3732深入GetMessage和PeekMessage (引自 ... -
界面编程总结(1)
2010-06-02 13:32 4017原文地址:http://blog.csdn.net/byx ... -
获取信息的有关Windows API
2010-05-27 10:01 3155获取信息的有关Windows API 1.窗口信息 ... -
VC中如何实现窗口的隐藏
2010-05-13 10:08 7875VC中如何实现窗口的隐藏 用MFC做的Dialog ... -
SetConsoleCtrlHandler 处理控制台消息
2010-05-07 17:32 18171SetConsoleCtrlHandler 处理控制台消 ... -
解决决错误: error C2850: 'PCH header file'
2010-04-27 19:45 1960解决决错误: error C2850: 'PCH hea ... -
VC++ GDI+编程的字体和文本绘制
2010-04-13 13:12 7990字体是文字显示和打印的外观形式,它包括了文字的字样、风格和尺寸 ... -
VC利用GDI+显示透明的PNG图片
2010-04-12 16:59 115561.在你将要使用GDI+的工程中,完成初始化 ... -
GDI+编程基础(一)GDI+ Vs GDI
2010-04-12 15:59 2342下载源代码一、GDI GDI是位于应用程序与不同硬件之间 ... -
VC画图
2010-04-12 15:50 1547BOOL DrawPic(HDC hdc, TCHAR* ... -
对话框的数据交换--MFC深入浅出
2010-04-12 10:43 2468对话框数据交换指以下两种动作,或者是把内存数据写入对应的控 ...
相关推荐
本文将深入探讨Winsock完成端口模型的工作原理、创建与使用,以及其在实际开发中的优势。 一、Winsock完成端口模型概述 Winsock 完成端口模型是基于异步I/O模型,允许应用程序在发起I/O操作后立即返回,无需等待...
《深入理解Winsock完成端口》 在Windows操作系统中,网络编程往往涉及到大量的并发连接处理,传统的套接字API在高并发环境下效率较低,而Winsock完成端口(IOCP,I/O Completion Port)机制正是为了解决这个问题而...
本压缩包“易语言源码winsock完成端口.rar”包含了易语言编写的一个特定的网络通信模块——Winsock完成端口(IOCP,I/O Completion Port)的源代码。IOCP是Windows操作系统中一种高效的多线程I/O处理机制,尤其适用...
易语言winsock完成端口源码,winsock完成端口,接受连接线程,取错误文本,ServerWorkerThread,socket,WSASocket,WSAAccept,closesocket,Connect,Send,recv,WSARecv,bind,WSAStartup,WSACleanup,htons,inet_ntoa,inet_...
易语言winsock完成端口.rar 易语言winsock完成端口.rar 易语言winsock完成端口.rar 易语言winsock完成端口.rar 易语言winsock完成端口.rar 易语言winsock完成端口.rar
《易语言实现Winsock完成端口的项目源码解析与应用》 易语言,作为一款中文编程语言,以其直观易懂的语法特性深受初学者和专业开发者喜爱。本项目源码——"winsock完成端口.zip",是针对网络编程中的关键概念——...
Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握 Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有一定的了解...
Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有一定的了解...
WinSock完成端口IO模型是Windows操作系统中一种高效、多线程的异步I/O处理方式,主要用于网络编程。这个模型充分利用了系统资源,优化了并发处理能力,尤其适合高并发的服务器应用。 首先,我们要了解重叠I/O的概念...
### 一个对Winsock完成端口模型封装的类的研究文档 #### 概述 本文档主要探讨了在Windows环境下如何高效地使用Winsock完成端口模型,并通过C++类的形式对该模型进行了封装,以简化网络服务端程序的开发流程。完成...
完成端口模型(I/O Completion Ports,简称IOCP)是一种高效、多线程的I/O管理机制,尤其适合处理大量并发连接。在Windows系统中,它被广泛应用于网络编程,如服务器应用程序,以提高性能和可扩展性。在这个Delphi...
Winsock的完成端口模型借助Widnows的重叠IO和完成端口来实现,完成端口模型懂了之后是比较简单的,但是要想掌握Winsock完成端口模型,需要对WINDOWS下的线程、线程同步,Winsock API以及WINDOWS IO机制有一定的了解....
Winsock 完成端口模型封装的类 Windows Sockets规范以U.C. Berkeley大学BSD UNIX中流行的Socket接口为范例定义了一套Micosoft Windows下网络编程接口。它不仅包含了人们所熟悉的Berkeley Socket风格的库函数;也包含...
"Winsock完成端口"是Windows系统中一种高级的I/O模型,主要用于处理大量并发的网络连接。在易语言环境中,这个概念可以帮助开发者构建高效、可扩展的网络应用程序。易语言是一种面向对象的中文编程语言,它提供了...