第一范文网 - 专业文章范例文档资料分享平台

完成端口

来源:用户分享 时间:2025/10/4 2:33:41 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

18. // 开始监听

19. listen(m_sockListen,SOMAXCONN))

需要注意的地方有两点:

(1) 想要使用重叠I/O的话,初始化Socket的时候一定要使用WSASocket并带上WSA_FLAG_OVERLAPPED参数才可以(只有在服务器端需要这么做,在客户端是不需要的);

(2) 注意到listen函数后面用的那个常量SOMAXCONN了吗?这个是在微软在WinSock2.h中定义的,并且还附赠了一条注释,Maximum queue length specifiable by listen.,所以说,不用白不用咯^_^

接下来有一个非常重要的动作:既然我们要使用完成端口来帮我们进行监听工作,那么我们一定要把这个监听Socket和完成端口绑定才可以的吧: 如何绑定呢?同样很简单,用 CreateIoCompletionPort()函数。

等等!大家没觉得这个函数很眼熟么?是的,这个和前面那个创建完成端口用的居然是同一个API!但是这里这个API可不是用来建立完成端口的,而是用于将Socket和以前创建的那个完成端口绑定的,大家可要看准了,不要被迷惑了,因为他们的参数是明显不一样的,前面那个的参数是一个-1,三个0,太好记了…

说实话,我感觉微软应该把这两个函数分开,弄个 CreateNewCompletionPort() 多好呢?

这里在详细讲解一下CreateIoCompletionPort()的几个参数:

[cpp] view plaincopy

1. HANDLE WINAPI CreateIoCompletionPort(

2. __in HANDLE FileHandle, // 这里当然是连入的这个套接字句柄

3. __in_opt HANDLE ExistingCompletionPort, // 这个就是前面创建的那个完成端

4. __in ULONG_PTR CompletionKey, // 这个参数就是类似于线程参数一

样,在

5. // 绑定的时候把自己定义的结构体

指针传递

6. // 这样到了Worker线程中,也可以

使用这个

7. // 结构体的数据了,相当于参数的传

8. __in DWORD NumberOfConcurrentThreads // 这里同样置0 9. );

这些参数也没什么好讲的吧,用处一目了然了。而对于其中的那个CompletionKey,我们后面会详细提到。

到此才算是Socket全部初始化完毕了。

初始化Socket完毕之后,就可以在这个Socket上投递AcceptEx请求了。 【第四步】在这个监听Socket上投递AcceptEx请求 这里的处理比较复杂。

这个AcceptEx比较特别,而且这个是微软专门在Windows操作系统里面提供的扩展函数,也就是说这个不是Winsock2标准里面提供的,是微软为了方便咱们使用重叠I/O机制,额外提供的一些函数,所以在使用之前也还是需要进行些准备工作。

微软的实现是通过mswsock.dll中提供的,所以我们可以通过静态链接mswsock.lib来使用AcceptEx。但是这是一个不推荐的方式,我们应该用WSAIoctl 配合

SIO_GET_EXTENSION_FUNCTION_POINTER参数来获取函数的指针,然后再调用AcceptEx。

这是为什么呢?因为我们在未取得函数指针的情况下就调用AcceptEx的开销是很大的,因为AcceptEx 实际上是存在于Winsock2结构体系之外的(因为是微软另外提供的),所以如果我们直接调用AcceptEx的话,首先我们的代码就只能在微软的平台上用了,没有办法在其他平台上调用到该平台提供的AcceptEx的版本(如果有的话), 而且更糟糕的是,我们每次调用AcceptEx时,Service Provider都得要通过WSAIoctl()获取一次该函数指针,效率太低了,所以还不如我们自己直接在代码中直接去这么获取一下指针好了。 获取AcceptEx函数指针的代码大致如下:

[cpp] view plaincopy

1.

2. LPFN_ACCEPTEX m_lpfnAcceptEx; // AcceptEx函数指针 3. GUID GuidAcceptEx = WSAID_ACCEPTEX; // GUID,这个是识别AcceptEx

函数必须的

4. DWORD dwBytes = 0; 5.

6. WSAIoctl(

7. m_pListenContext->m_Socket,

8. SIO_GET_EXTENSION_FUNCTION_POINTER, 9. &GuidAcceptEx, 10. sizeof(GuidAcceptEx), 11. &m_lpfnAcceptEx, 12. sizeof(m_lpfnAcceptEx), 13. &dwBytes, 14. NULL, 15. NULL);

具体实现就没什么可说的了,因为都是固定的套路,那个GUID是微软给定义好的,直接拿过来用就行了,WSAIoctl()就是通过这个找到AcceptEx的地址的,另外需要注意的是,通过WSAIoctl获取AcceptEx函数指针时,只需要随便传递给WSAIoctl()一个有效的SOCKET即可,该Socket的类型不会影响获取的AcceptEx函数指针。

然后,我们就可以通过其中的指针m_lpfnAcceptEx调用AcceptEx函数了。 AcceptEx函数的定义如下:

[cpp] view plaincopy

1. BOOL AcceptEx (

2. SOCKET sListenSocket, 3. SOCKET sAcceptSocket, 4. PVOID lpOutputBuffer, 5. DWORD dwReceiveDataLength, 6. DWORD dwLocalAddressLength, 7. DWORD dwRemoteAddressLength, 8. LPDWORD lpdwBytesReceived, 9. LPOVERLAPPED lpOverlapped 10. );

乍一看起来参数很多,但是实际用起来也很简单:

? ?

参数1--sListenSocket, 这个就是那个唯一的用来监听的Socket了,没什么说的; 参数2--sAcceptSocket, 用于接受连接的socket,这个就是那个需要我们事先建好的,等有客户端连接进来直接把这个Socket拿给它用的那个,是AcceptEx高性能的关键所在。

? 参数3--lpOutputBuffer,接收缓冲区,这也是AcceptEx比较有特色的地方,既然AcceptEx不是普通的accpet函数,那么这个缓冲区也不是普通的缓冲区,这个缓冲区包含了三个信息:一是客户端发来的第一组数据,二是server的地址,三是client地址,都是精华啊…但是读取起来就会很麻烦,不过后面有一个更好的解决方案。

? 参数4--dwReceiveDataLength,前面那个参数lpOutputBuffer中用于存放数据的空间大小。如果此参数=0,则Accept时将不会待数据到来,而直接返回,如果此参数不为0,那么一定得等接收到数据了才会返回…… 所以通常当需要Accept接收数据时,就需要将该参数设成为:sizeof(lpOutputBuffer) - 2*(sizeof sockaddr_in +16),也就是说总长度减去两个地址空间的长度就是了,看起来复杂,其实想明白了也没啥……

? ? ? ?

参数5--dwLocalAddressLength,存放本地址地址信息的空间大小; 参数6--dwRemoteAddressLength,存放本远端地址信息的空间大小; 参数7--lpdwBytesReceived,out参数,对我们来说没用,不用管; 参数8--lpOverlapped,本次重叠I/O所要用到的重叠结构。

这里面的参数倒是没什么,看起来复杂,但是咱们依旧可以一个一个传进去,然后在对应的IO操作完成之后,这些参数Windows内核自然就会帮咱们填满了。

但是非常悲催的是,我们这个是异步操作,我们是在线程启动的地方投递的这个操作, 等我们再次见到这些个变量的时候,就已经是在Worker线程内部了,因为Windows会直接把操作完成的结果传递到Worker线程里,这样咱们在启动的时候投递了那么多的IO请求,这从Worker线程传回来的这些结果,到底是对应着哪个IO请求的呢?。。。。 聪明的你肯定想到了,是的,Windows内核也帮我们想到了:用一个标志来绑定每一个IO操作,这样到了Worker线程内部的时候,收到网络操作完成的通知之后,再通过这个标志来找出这组返回的数据到底对应的是哪个Io操作的。 这里的标志就是如下这样的结构体:

[cpp] view plaincopy

1.

2. typedef struct _PER_IO_CONTEXT{

搜索更多关于: 完成端口 的文档
完成端口.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c1rqew0ukch8xzko047iq_5.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top