通用性IOCP网络模型
来源:互联网 发布:网络教育要交几年学费 编辑:程序博客网 时间:2024/05/16 16:08
同步,异步,阻塞,非阻塞之间的关系。
所谓同步和异步,就是应用程序等待api与否,应用程序等待api,就是同步,不等待,就是异步。
假设一个api需要10秒钟执行完成,应用程序调用api,操作系统切换到内核态,同时挂起应用程序,直到操作系统执行完毕,把结果返回给应用程序,就是同步调用。
而应用程序把api请求投递给操作系统,操作系统收到请求后执行api,此时操作系统来决定要不要挂起这个应用程序(如果挂起就是阻塞,不挂起就是非阻塞),如果操作系统不挂起这个程序,程序就可以去执行别的东西,直到某一刻收到操作系统的通知或者主动查询结果,这就是异步调用。
而阻塞和非阻塞主要用于io操作,上面已经提到过,操作系统api执行的时候,需要挂起应用程序,直到io完成后恢复应用程序,这就是阻塞。如果操作系统不挂起应用程序,而是按照常规的cpu时间片分配运行进程,直到完成io操作为止(完成时可能通知调用程序,也可能不通知),就是非阻塞。
基本io模型:
1. block/多线程block
同步发送/接收,会在没有数据的时候阻塞住,需要线程太多,并发性不高。
2. select
选择模型,bsd套接字模型,关键在于使用select "偷窥" 指定的fd_set里面有没有数据,可不可写(用的较少),有没有错误,再用fd_isset判断后执行发送/接收操作。缺点在于空循环会浪费时间,而且可能产生很多wouldblock错误。
3. WSAAsyncSelect
通过对指定socket注册感兴趣的事件,并制定接收窗口来处理消息,只在窗口应用程序中有用。
4. WSAEventSelect (对应于unix的信号驱动模型)
通过对指定socket注册感兴趣的事件给某个WSAEVENT,当事件触发的时候会触发这个event,可以用WSAWaitForMultipleEvents获取消息事件。
相比select省略了空循环t的时间,WSAWaitForMultipleEvents是同步函数。
5. overlapped(对应于unix的异步模型)
把io处理和结果分开来,异步非阻塞的投递io请求,之后通过回调函数处理返回结果。
相比于前一种模型overlapped模型不用注册wsaevent,而是在调用api的时候指定overlapped结构的指针,再通过WSAWaitForMultipleEvents得到事件结果。
6. IOCP
iocp模型在overlapped之上增加了完成端口概念,用于处理大量数据缓存。完成端口是一个系统内核,通过createiocompletionport创建得到句柄,之后通过句柄来访问,关闭时调用closehandler就可以了。
在使用时,通过getqueuedcompletionstatus得到调用的结果,再对结果进行处理。
简单的完成端口使用实例。
需要的资源:
1. 一个监听线程
2. 若干个完成端口,可以配合若干线程使用。这些线程不断的获取io操作的结果,并加以处理。
3. 维护tcp/udp连接的类conn,用来保存接受/发送的数据缓存,socket,以及oop回调等。
4. 一个定时线程,用来处理一些延时请求,比如重连延迟等。
初始化:
1. wsastartup
2. 服务启动的时候调用Init函数,指定服务的类型(server,client,混合等)
3. 创建n个完成端口,绑定在线程中用来处理iocp请求回调。
4. 由于udp监听是没有连接可供accept的,需要的话可以让其中的一些线程指定udp处理。
socket属性:
tcp: AF_INET, SOCK_STREAM, ..... WSA_FLG_OVERLAPPED
setsocketopt —— (SOL_SOCKET)SO_KEEP_ALIVE, SO_SNDBUF, SO_RECVBUF, SO_REUSEADDR, (IPPROTO_TCP) TCP_NODELAY
udp: AF_INET, SOCK_DGRAM
setsocketopt —— (SOL_SOCKET) SO_REUSEADDR
注:由于overlapped自动把socket设置为非阻塞,这里就不用调用ioctlsocket(, FIONBIO,) 了。
工作线程:
1. 如果有udp监听需要,创建一个socket,用createiocompletionport绑定到iocp中,并在工作者线程中投递wsarecv/wsarecvfrom请求
2. 处理其他连接创建后(如accept/connect创建的socket)投递请求
3. 通过循环getqueuedconpletionstatus函数得到io处理结果,可以得到传输的数据,socket号,overlapped结构体。可以用socket号得到确切的io操作者,也可以通过overlapped结构体指针使用containing_record函数获得包含这个指针的类。(overlapped结构体就是调用wsasend/recv时传递的那个),这么做的好处是不用在查询socket归属的类容器时上锁(因为有新连接加入时的插入可能会造成冲突)
4. 根据overlapped结构体的oerpation参数得到该返回值的类型,处理数据接收或者标志数据发送完成。
创建监听:
1 . 通过ip/port值创建sockaddr_in结构体,创建一个sck,并绑定sck和sockaddr_in,使用listen创建监听。
2. 创建一个新线程,这个线程用空循环不断的wsaacept
3 当有新连接接入时,创建一个conn,绑定相关的回调资源,绑定给某个完成端口(处于负载均匀的考虑,可以查询所有线程的负载情况决定,也可以简单的用sck值取模决定)
4. 在工作线程中投递接受请求
连接远程sck:
1. 创建一个conn类,保存相关数据和回调
2. 通过ip/port值创建sockaddr_in结构体,创建sck,通过connect连接。若成功,tcp socket会自动被操作系统绑定到一个系统空闲端口。
3. 如果连接成功,把这个sck绑定给完成端口和相关线程4
4. 在工作线程中投递接受请求
发送数据:
1. 在调用者线程中通过send/sendudp发送。
2. 如果调用者很多,可以通过fiber或者新线程来管理这些发送。
3, 发送最终会通过getqueuedcompletionstatus返回,在工作者线程中可以得到结果。
注:iocp的tcp发送时一个阻塞过程,除非inv - inv/ack - ack这个过程完成,否则getqueuedcompletionstatus不会返回。这就意味着如果某些客户端不返回ack,iocp的发送请求会越来越多,导致系统资源被耗尽(当然系统也有一些处理这种情况的措施,比如增加请求的数量判断等),所以在发送前可以指定一些请求的数量限制,发送时数量+1,得到结果后数量-1,当达到上限就强制关闭socket
接收数据:
1. 在绑定iocp后就可以调用wsarecv投递请求了。
2. 接收请求最终会通过getqueuedcompletionstatus返回,如果返回字节数为0说明客户端主动关闭连接(当然某些iocp_recvzero的操作除外)。
3. 由于我们调用recv的时候把数据缓冲区指定了,所以得到回复之后直接访问缓冲区里面的数据就可以了,这时候保存缓冲区的conn可以通过回调通知应用程序。
4. 如果缓冲区不够写,或者其他出错情况
关闭sck:
1. 在工作线程里面加入该conn的关闭函数
2. 关闭时先调用shutdown关闭数据收发
3. 处理剩余数据,掉用关闭回调,closesocket
关闭服务(线程):
通过postqueuedconpltionsttus给iocp句柄发送消息,然后通过waitforsingleobject终止线程
重连的情况:
在timequeue里面插入sck操作,定时调用
相关资料:
http://blog.csdn.net/historyasamirror/article/details/4270633 (同步异步等概念)
http://blog.csdn.net/phunxm/article/details/5085869 (winsock基础)
http://blog.csdn.net/phunxm/article/details/5085898 (winsock模型)
http://www.cppblog.com/Lee7/archive/2008/01/07/40650.html (overlapped和iocp的关联)
http://www.cnblogs.com/cylee025/archive/2011/10/22/2221476.html
- 通用性IOCP网络模型
- IOCP网络模型
- IOCP网络模型
- IOCP网络模型基本步骤
- IOCP模型与网络编程
- IOCP网络模型基本步骤
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- IOCP模型与网络编程
- 因为一首歌,想念一个人?
- .net 密码框赋值、输入以及页面刷新状态下的处理过程
- Dictionary 与object
- Prism学习笔记(一) 从Hello World开始
- VSTS
- 通用性IOCP网络模型
- Android开发者必须深入学习的10个应用开源项目
- Prism学习笔记(二)简单的MVVM模式
- 2011年十大开源软件
- Flex application创建顺序(转)
- 不一样的Python(7)——函数
- Prism之Bootstrapper
- 两列不定宽自适应布局
- JPEG File Format