accept和AcceptEx在性能上区别不大

时间:2021-07-14 06:21:04

标签:

1 Windows完成端口根基介绍


2他是只能在Windows下的基于SOCKET事件打点的模型

3与select差别,select需要多次重置打点句柄,IOCP只要一次

4有事件后select需要操纵获取数据,而IOCP通知你的时候说明数据操纵好了

5select打点句柄的数目有限,IOCP没有限制

6IOCP撑持多线程同时期待。


我的设计思路一个线程用来侦听accept事件, 一个线程来侦听SOCKET的IO事件,

大部分框架都是这样, 其实可以只使用一个线程做异步SOCKET就完全足够了,此刻

使用多线程来 就是看看这个IOCP的多线程用法,


在这之前先要了解下 异步通信 和 重叠I/O模型

异步通信机制:

重叠I/O模型: 


我建议使用单线程 原因: 应为多个线程,拿到数据后,还是要发送到此外一个线程里面去,

然后做成事件行列队伍, 也就是你线程拿到数据后, 还是要按行列队伍线程,进行逻辑措置惩罚惩罚,多线程没意义。



2完成端口内部运行流程

完成端口的做法:事先开好几个线程,你有几个CPU我就开几个,首先是制止了线程的上下文切换,因为线程想要

执行的时候,总有CPU资源可用,然后让几个线程等着,等到有用户请求到来的时候,就把这些请求都插手到一个

大众动静行列队伍中, 然后这几个开好的线程就排队逐一去从动静行列队伍中取出动静并加以措置惩罚惩罚, 这种方法实现了

异步通信和负载均衡的问题,因为他供给了一种机制来使用个线程"公平的"措置惩罚惩罚来自多个客户真个输入/输出

,并且线程如果没事干的时候,也会被系统挂起,,不会占用CPU



3WSAAsyncSelect或者WSAEventSelect和完成端口

WSAAsyncSelect或者WSAEventSelect两种异步模型, 这两种模式必然没有使用overlapped(重叠)机制,

就不能算是真正的异步,可能是其内部维护了一个动静行列队伍,这两个模式虽然实现了异步接收,却不能异步的发送,

完成端口他是先把用户数据接收回来后在通知用户直接来取,而这两种模式只会接到数据达到的通知,只能是由

应用措施本身去recv数据,性能上就发送了差异

要实现异步通信, 就要一个很强的I/O数据布局,叫重接结"Overtlapped",

Window所有异步通信都是基于他,完成端口也不例外

就是执行I/O请求的时间与线程执行其他任务的事件是重叠(overlapped)的,


重叠布局是异步通信机制实现的一个核心数据布局,因为几乎所有的网络操纵例如发送/接收,都要用

WSASend()和WSARecv()取代,参数里面城市要附带一个重叠布局,因为重叠机构可以理解为是一个

网络操纵的ID号,也就是说我们要操作重叠I/O供给的异步机制的话,每一个网络操纵都要有一个独一的ID号,

因为进来系统内核,一看到有重叠的I/O的挪用进来了,就会使用其异步机制,并且操纵系统就只能靠

这个重叠布局带有的ID号来区分是哪一个网络操纵了,然后内核里措置惩罚惩罚完毕, 按照这个ID号,把对应的数据传上去.




4完成端口根基的使用流程 

完成端口也分法式的

1挪用CreateIoCompletionPort()函数创建一个完成端口,而且在一般情况下,我们需要并且只需要

成立一个完成端口,把他的句柄生存好, 之后只要使用这一个句柄就行了。

2按照和客户的I/O操纵最好是本身建一个事情线程

3接入Socket连接, 有两种方法,1是和另外模型一样,有一个独立的线程,专门来accept客户真个连接,

二是用性能更好的异步AcceptEx()请求

4每当有客户端进来的时候,还是挪用CreateIoCompletionPort()函数,这里不是成立完成端口,

而是把新连入的Socket句柄, 和你创建的完成端口绑定在一起。

5客户端连入后,我们要向这个客户端Socket提交一个请求,如接收文件要挪用WSARecv()然后系统

就会去执行接收数据的操纵, 就不用我们管了。

6 然后就要挪用GetQueuedCompletionStatus()(是一个梗阻函数)里面是扫描端口的行列队伍里是否有

网络通信的请求存在(例如读取数据,发送数据等),一旦有,就会将这个请求从完成端口的行列队伍取回来,

继续执行本线程的后续代码,措置惩罚惩罚完毕后, 必需要再次 投递网络通信请求(WSARecv),如此循环。




5AcceptEx和Accept的区别

AcceptEx和Accept最大的区别,就是打消了梗阻方法的accept挪用,也就是说AccentEx也是通过

完成端口来异步完成的。

这样做的好处就是:如果短时间内客户端并发连接请求不是很多,accept和AcceptEx在性能上区别不大,

虽然我们创建Socket只用一行SOCKET s =socket(...)一行代码,但是系统内部成立一个Socket是相当

耗费资源的,因为Winsock2是分层的机构体系,创建一个Socket需要用到多个Provider之间进行措置惩罚惩罚,

最终形成一个可用的套接字,总之,创建一个Socket的高兴是相当高的。

AcceptEx比Accept强三点:

(1)最关键的是AcceptEx在客户端连入之前,就把客户真个Socket成立好了,也就是说,AcceptEx是先成立

Socket,然后发出的AcceptEx挪用,也就是说,在进行客户真个通信之前,无论是否有客户端连入,

Socket都是提前成立好的,而不需要想accept是在客户端连入之后,在现场话费时间成立Socket,

(2)对比Accept只能梗阻方法成立一个连入的入口,对付大量的并发客户端来讲,是在是有点挤,

而AcceptEx可以在完成端口上投递多个请求,还有客户端连入的时候,就非常优雅而且从容.

(3)AcceptEx还有一个长处,就是投递AccepEx的时候,收取客户端发来的第一组数据,这是同时

进行的, 也就意味着,如果客户端只是连入但不发送数据的话,我们就不会收到这个AccepeEx完成的通知,

异步的AcceptEx使用起来比accept要麻烦。



由于时间关系,不才篇博客 会详细介绍完成端口的用法

实现图片中的成果