完成端口与AcceptEx

关于IOCP网上到处都是资料,说的也很详细。我在这里就不再多说了,这只是本人在学习IOCP时的笔记,和配合AcceptEx写的一个极小的服务端程序。由于刚刚接触ICOP加上本人刚毕业不到一年,所以里面的理解或观点可能有误,还请大家多多批评!

         VC6.0开发,旨在体现IOCP的架构,忽略细节,服务程序的功能只是接收客户连接,接着接收到客户数据,然后原封不动的返回给客户!

 

下面这段话,如果不感兴趣,可以跳过去,直接看代码...

先说IOCP,其实思路很清晰:

         1.声明一个数据结构,用来存放客户套接字和客户信息

         2.声明一个包含OVERLAPPED字段的I/O结构

         3.创建完成端口

         4.创建服务线程

         5.接收客户端连接请求

         6.关联这个套接字到完成端口中

         7.服务线程中不断的等待I/O结果,在结果中提供服务和根据需要发起另一个异步操作。

 

         按照这个思路很快的写出了一个服务程序,但是遇到了下面的问题:

         1.WSAGetLastError()返回10045,找了半天才发现发起重叠操作时候,WSARecv中flag参数没有初始化,需要初始化赋值为0。

         2.在GetQueuedCompletionStatus中,没有错误,但总是返回读取的字数为0。I/O重叠结构中也收不到任何字符。这时候我就在这里用了一下recv()函数,在recv中却可以收到来自客户端发送的数据。难道每次都要自己recv()?肯定不是!如果那样还用扩展的I/O结果何用。一定是哪里指定了接收的数目,而自己不小心指定为0了,所以没有接收数据。找了半天果然如此。在发起重叠操作时候,扩展的I/O中WSABUF的赋值有问题。

         我的错误:wsaBuf.len = (I/O结构).len;

         改为:       wsaBuf.len = (I/O结构).len = DATABUF_SIZE;

         修改之后终于可以接收和发送数据了。

 

 

为什么要用AcceptEx?

         在学习IOCP时,看到一位大神写的文章,他用客户端开了3W个线程同时连接服务端和发送数据,我好奇就也开了3W个线程去同时连接服务端,结果很多都printf连接失败的信息!再看看大神的文章,再搜一下AcceptEx。对比accept,觉得AcceptEx确实很强大。AcceptEx和accept主要的区别就在于接收套接字:

         accept函数是等待客户连接进来之后才创建套接字,虽然在我们看到的就是一个socket函数,但是在函数背后,系统应该会消耗不少资源,因为它要打通一个和外界通讯的路。如果大量套接字并发接入,难免有的套接字不能及时创建和接收。

         AcceptEx则是事先创建好套接字,坐等客户端的连接就行了。

 

         但是,AcceptEx相比accept确实复杂了很多。原来一句accept就可以解决的,现在却要为AcceptEx做很多服务,但是只要理清思路,这个做起来也是很从容的。

         1.创建一个监听套接字

         2.将监听套接字关联到完成端口中

         3.对监听套接字调用bind()、listen()

         4.通过WSAIoctl获取AcceptEx、GetAcceptExSockaddrs函数的指针

         5.创建一个用于接收客户连接的套接字

         6.用获取到的AcceptEx函数指针发起用于接收连接的异步操作

         7.服务器接收到连接的套接字,设置一下它的属性(有人说没有必要)。用这个接收到的套接字去发起重叠的I/O操作。

         8.多次重复5,6就是多次发起接收连接的异步操作的过程。

         对于第4步,为什么要获取AcceptEx的指针,而不是直接就调用AcceptEx这个函数呢?网上找到的资料是这么说的:

         Winsock2的其他供应商不一定会实现AcceptEx函数。同样情况也包括的其他Microsoft的特定APIs如TransmitFile,GetAcceptExSockAddrs以及其他Microsoft将在以后版本的windows里。

在运行WinNT和Win2000的系统上,这些APIs在Microsoft提供的DLL(mswsock.dll)里实现,可以通过链接mswsock.lib或者通过WSAioctl的SIO_GET_EXTENSION_FUNCTION_POINTER操作动态调用这些扩展APIs.

未获取函数指针就调用函数(如直接连接mswsock.lib并直接调用AcceptEx)的消耗是很大的,因为AcceptEx实际上是存在于Winsock2结构体系之外的。每次应用程序常试在服务提供层上(mswsock之上

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值