Socket I/O模型如下:
select模型
循环去检查是否有新事件,可读,可写,错误信息,再做相应操作
WSAAsyncSelect模型
注册消息事件,当有新事件发生时,系统发送一个消息给你
WSAAsyncSelect必须指定一个窗口句柄,自定义消息ID,要监听网络事件类型
消息的wParam表示发生网络事件的套接字
WSAGETSELECTERROR(lParam);//查看是否出现错误,获取低字节位
WSAGETSELECTEVENT(lParam);//查看发生了什么事件,获取高字节位
WSAEventSelect模型 事件选择模型
等待多个信号,有消息时,信号灯亮,通知你接收
WSAEventSelect事件对象创建好后,必须将其与某个套接字关联在一起,同时注册感兴趣的网络事件类型
WSAWaitForMultipleEvents等事件,在同一个线程中,最多只能等待64个事件
WSAEnumNewWorkEvents检查发生了什么类型的网络事件
Overlapped I/O 事件通知模型
等待多个事件,有事件消息时,事件通知你接收Overlapped结构
WSAEVENT hEvent=WSACreateEvent();
Overlapped.hEvent=hEvent
将Overlapped做为WSARecv参数
WSAWaitForMultipleEvents等事件,在同一个线程中,最多只能等待64个事件
有事件后用WSAGetOverlappedResult接收IO数据
Overlapped I/O 完成例程模型
操作数据时,提供一个回调函数,有网络事件时,系统调用回调函数
WSARecv指定WorkerRoutine回调函数
完成例程模型相比与事件通知模型有个很大的优点就是不再受64个消息的限制,
一个线程可以同时管理成百上千个socket连接,且保持较高的性能
完成例程相比与完成端口较为逊色,因为它的性能不能随着系统CPU数量的增长而线性增长
IOCP模型,完成端口
建立完成端口,把accept到的socket与完成端口关连,之后就可以在这个完成端口上接收这个socket的网络事件
m_CompetionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
CreateIoCompletionPort((HANDLE)acceptsocket,m_CompetionPort,(DWORD)pClient,0);
GetQueuedCompletionStatus(m_CompetionPort ,&BytesTransferred,
(LPDWORD)&pClient,(LPOVERLAPPED*)&OverlappedHead,waittime);
linux
epoll模型
epoll_create 创建一个epoll的句柄
epoll_ctl 注册监听事件
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
epoll_wait 等待事件的产生