完成端口中ConnectEx的问题:
完成端口用于客户端时一定要注意,创建的SOCKET要先随便绑定一个端口(默认0自动分配也可),然后再扔到完成端口中去,之后才可以ConnectEx,否则(不绑定),ConnectEx会出现10022错误。同时,getpeername似乎对ConnectEx不支持,也可能有其他细节设置我暂时不知道,返回的远程地址是无效的(仅对于完成端口用于服务器accept回来的SOCKET有效,对用于客户的connet也有效)。不过对程序没有太大影响,既然是自己要主动连出去,远程地址当然自己早就心里明白了,自己保存一份即可,不必getpeername。备注:getsockname返回本地地址一直是有效的。
getpeername之所以取不到正确的内容,是因为ConnectEx返回后,socket相关的属性还没有更新(ConnectEx的特性所导致),你应该调用一下setsockopt更新socket的属性后再调用getpeername。参数是SOL_SOCKET和SO_UPDATE_CONNECT_CONTEXT。
When the ConnectEx function returns, the socket s is in the default state for a connected socket. The socket s does not enable previously set properties or options until SO_UPDATE_CONNECT_CONTEXT is set on the socket. Use the setsockopt function to set the SO_UPDATE_CONNECT_CONTEXT option.
For example:
err = setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
完成端口与ACE框架:
平台不同,使用的ACE框架还是有所差别的。比如windows下面的服务器端,一般都用Proactor框架,配合各种异步操作,如ACE_Asynch_Acceptor/ACE_Asynch_Connector,因为Proactor内部实现是完成端口,在windows平台上,公认可以取得最好的性能。
如果你用Linux,服务器端推荐你使用Reactor框架+Dev_Poll_Reactor实现,这个实现使用了Epoll机制,性能很棒。
客户端,一般为了兼容性考虑,都用Reactor,当然,如果是在windows上面运行,默认实现是WFMO_Reactor。
IOCP(I/O completion port,I/O完成端口)是伸缩性最好的一种I/O模型。本章将具体讨论完成端口的概念和它的用法,讲述可伸缩性服务器的体系结构,最后结合实例介绍使用IOCP进行可伸缩服务器程序设计的过程。
4.1 完成端口I/O模型
当应用程序必须一次管理多个套接字时,完成端口模型提供了最好的系统性能。这个模型也提供了最好的伸缩性,它非常适合用来处理上百、上千个套接字。IOCP技术广泛应用于各种类型的高性能服务器,如Apache等。本节将结合一个简单的例子详细讨论它的用法。
4.1.1 什么是完成端口(completion port)对象
I/O完成端口是应用程序使用线程池处理异步I/O请求的一种机制。处理多个并发异步I/O请求时,使用I/O完成端口比在I/O请求时创建线程更快更有效。
I/O完成端口最初的设计是应用程序发出一些异步I/O请求,当这些请求完成时,设备驱动将把这些工作项目排序到完成端口,这样,在完成端口上等待的线程池便可以处理这些完成I/O。完成端口实际上是一个Windows I/O结构,它可以接收多种对象的句柄,如文件对象、套接字对象等。本节仅讲述使用完成端口模型管理套接字的方法。