|
|
翻译说明:
完成端口基本上公认为一种在windows服务平台上比较成熟和高效的IO方法,理解和编写程序都不是很困难。目前我正在进行这方面的实践,代码还没有完全调试和评价,只有这一篇拙劣的学习翻译文摘,见笑见笑。
翻译这个文章,是因为我近期在学习一些socket服务程序的编写中发现(注意,只是在学习,我本人在这个领域经验并不充足到可以撰文骗钱的地步:P),如果不是逼着自己把这个文章从头翻译一遍,我怀疑我是否能认真领会本文的内容 :PPP. 把这个文章贴出来,不是为了赚人气,而是因为水平确实有限,虽然整体上大差不差的翻译出来了,但是细节和用词上可能还是有很多问题。是希望大家能指出其中的翻译错误和理解谬误,互相交流和帮助。非常感谢。
本文翻译并没有通过原作者同意,仅用来在网络上学习和交流,加之翻译水平拙劣,所以请勿用于做商业用途。
vcbear
2001.8
Windows Sockets 2.0:使用完成端口高性能,可扩展性Winsock服务程序
原作者:Anthony Jones 和Amol Deshpande
原文在http://msdn.microsoft.com/msdnmag/issues/1000/winsock/winsock.asp
本文作者假定你已经熟悉Winsock API,TCP/IP ,Win32 API
摘要:编写一般的网络应用程序的难点在于程序的“可扩展性”。利用完成端口进行重叠I/O的技术在WindowsNT和WIndows2000上提供了真正的可扩展性。完成端口和Windows Socket2.0结合可以开发出支持大量连接的网络服务程序。
本文从讨论服务端的实现开始,然后讨论如何处理有系统资源约束和高要求的环境,以及在可扩展的服务程序开发的过程中会遇到的一般问题。
--------------------------------------------------------------------------------
正文:
开发网络程序从来都不是一件容易的事情,尽管只需要遵守很少的一些规则�创建socket,发起连接,接受连接,发送和接受数据。真正的困难在于:让你的程序可以适应从单单一个连接到几千个连接。本文主要关注C/S结构的服务器端程序,因为一般来说,开发一个大容量,具可扩展性的winsock程序一般就是指服务程序。我们将讨论基于WindowsNT4.0和Windows 2000的代码,而不包括Windows3.x(什么时候的东西了),因为Winsock2的这一属性只在Windows NT4和最新版本上有效。
APIs和扩展性
win32重叠I/O(Overlapped I/O)机制允许发起一个操作,然后在操作完成之后接受到信息。对于那种需要很长时间才能完成的操作来说,重叠IO机制尤其有用,因为发起重叠操作的线程在重叠请求发出后就可以自由的做别的事情了。
在WinNT和Win2000上,提供的真正的可扩展的I/O模型就是使用完成端口(Completion Port)的重叠I/O.
其实类似于WSAAsyncSelect和select函数的机制更容易兼容Unix,但是难以实现我们想要的“扩展性”。而且windows的完成端口机制在操作系统内部已经作了优化,提供了更高的效率。所以,我们选择完成端口开始我们的服务器程序的开发。
完成端口(Completion Ports )
其实可以把完成端口看成系统维护的一个队列,操作系统把重叠IO操作完成的事件通知放到该队列里,由于是暴露 “操作完成”的事件通知,所以命名为“完成端口”(COmpletion Ports)。一个socket被创建后,可以在任何时刻和一个完成端口联系起来。
一般来说,一个应用程序可以创建多个工作线程来处理完成端口上的通知事件。工作线程的数量依赖于程序的具体需要。但是在理想的情况下,应该对应一个CPU创建一个线程。因为在完成端口理想模型中,每个线程都可以从系统获得一个“原子”性的时间片,轮番运行并检查完成端口,线程的切换是额外的开销。在实际开发的时候,还要考虑这些线程是否牵涉到其他堵塞操作的情况。如果某线程进行堵塞操作,系统则将其挂起,让别的线程获得运行时间。因此,如果有这样的情况,可以多创建几个线程来尽量利用时间。
应用完成端口分两步走:
1创建完成端口句柄:
HANDLE hIocp;
hIocp = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL,
(ULONG_PTR)0,
0);
if (hIocp == NULL) {
// Error
}
注意在第一个参数(FileHandle)传入INVALID_FILE_HANDLE,第二个参数(ExistingCompletionPort)传入NULL,系统将创建一个新的完成端口句柄,没有任何IO句柄与其关联。
2.完成端口创建成功后,在socket和完成端口之间建立关联。再次调用CreateIoCmpletionPort函数,这一次在第一个参数FileHandle传入创建的socket句柄,参数ExistingCompletionPort为已经创建的完成端口句柄。
以下代码创建了一个socke
网友评论:(评论内容只代表网友观点,与本站立场无关!) |
阅读排行
|