服务器开发基础-Tcp/Ip网络模型—完成端口(Completion Port)模型

服务器开发基础-Tcp/Ip网络模型—完成端口(Completion Port)模型

本文对于初学网络编程的极为友好,文中所有代码全部基于C语言实现,文中见解仅限于作者对于完成端口的初步认识,由于作者才疏学浅,出现的错误和纰漏,麻烦您一定要指出来,咱们共同进步。谢谢!!!


 

完成端口(completion Port)

 

前言:

网络通信分为两种:同步和异步。

  在同步通信中,每一次接受数据都会导致主线程的挂起,从而阻塞住了其他操作。为了解决这一问题,我们通常会采取同步通信+多线程的策略,即为每一个连入的Socket分配一个线程。然而随着连入的Socket的数量的增加,线程的数量也在增加,这样CPU则需要不停地进行线程的切换,因此难以成为高性能的服务器程序。
  异步通信则可以把接收数据这一操作交给内核,即在内核接收数据的时候,主线程可以不用被阻塞并且继续执行其他操作,而一旦接收数据完成以后,再由内核通知主线程。而如何通知主线程是一个关键,不同的异步通信策略有着不同的通知方式。
  在这样的情况下,完成端口这一I/O模型被提出,成为目前Windows下性能最好的I/O模型之一。

 (注:文中所有函数参数均已MSDN上的为标准,文中观点仅代表个人理解,如有错误,还请多多包涵并及时留言,我会第一时间改正,谢谢!!!)

完成端口模型简介:

上面所说的“初学”指你已经熟悉Socket进行TCP/IP编程的基本原理,前期基本的概念我这里就略过不提了,直入主题。

嗯~~!怎么说呢,完成端口是Windows的一种机制,这种机制是在重叠IO上的优化,所以说完成端口也是基于重叠结构的,换句话说如果对于重叠IO结构特别熟悉的话,那么完成端口对于你来说就特别简单。为什么说完成端口是在重叠IO上的一种优化呢?对比一下下面第一张和第二转张结构图,一定会有人好奇,为什么两张图差不多一样呢?仔细看会发现完成端口结构图里面操作系统有一步操作是将通知放进队列(第三张结构图,模仿消息队列原理系统会创建一个通知队列)。到这就可以说明完成端口在重叠IO具体优化的是什么了,熟悉重叠IO的都知道,重叠IO最严重的问题就是线程数量,有多少的客户端,那就得有多少根线程。肯定会有人说线程多了不是更好吗?速度跟快吗?程序执行时间更短码?那就错了,恰恰是相反的,上面我也大致提到了线程太多的问题。了解操作系统的都知道,线程在一个周期内分得的时间越多,那么执行就越快。换而言之如果线程数量增加,那么每根线程上所分得的时间就会变短,再加上切换线程的时间,这样一来反而时间更久。而理论上最优的线程数就是和CPU核数一样(还有其他的几种:CPU核数*2、CPU核数*2+2。为什么会有这几种情况,这里就不多多介绍了。)这样以来就可以充分的利用CPU资源。不过这也要求线程函数中没有调用诸如Sleep(),WSAWaitForMultipleEvents()…这类函数,这类函数会使线程挂起(但不占cpu时间片),从而使得CPU某个核空闲了,这就不好了,所以一般我们多建个两三根,以解决此类情况,让CPU不停歇,从而在整体上保证程序执行效率。本文采取的是和CPU核数一样多。而对于重叠IO中的无序性问题,完成端口采用了上述所说的创建一个通知队列(第三张结构图)来进行管理,从而达到有序。所以说完成端口是对重叠IO的改进也不为过。

    

完成端口原理以及部分函数用法:

1.CreateIoCompletionPort()函数创建一个完成端口。

对于 CreateIoCompletionPort()函数它有两个功能一个功能是创建完成端口,另一个功能就是将SOCKET与完成端口进行绑定,在这里就是创建完成端口。至于说功能不一样,也就是参数不同而已。

 

 HANDLE WINAPI CreateIoCompletionPort(  
    __in      HANDLE  FileHandle,           
     __in_opt  HANDLE  ExistingCompletionPort, 
     __in      ULONG_PTR CompletionKey,       
     __in      DWORD NumberOfConcurrentThreads 
);  
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 服务器开发基础-Tcp/Ip网络模型—完成端口(Completion Port)模型