socket非阻塞模型学习

socket非阻塞模型学习

1、select 模型
int select(
 int nfds,   //忽略,兼容Berkeley套接字
 fd_set* readfds,  //可读套接字集合
 fd_set* writefds,  //可写套接字集合
 fd_set* exceptfds,  //指向套接字集合,检查错误
 const struct timeval* timeout //超时时间,NULL为无限等待
 );
typedef struct fd_set {
 u_int fd_count;   //数组大小
 SOCKET fd_array[FD_SETSIZE]; //socket数组
}

预定义的4个操作fd_set的常用宏:
FD_ZERO(*set) 初始化set为空,清空集合
FD_CLR(s,*set) 从set移除s
FD_ISSET(s,*set)检查s是否在set中,true-存在
FD_SET(s,*set) 添加s到set中

评价:
单线程可以处理多个socket,但是需要不断进行对select返回的结果进行检查,性能不高
2、WSAAsyncSelect 模型
异步Windows消息通知模型

非阻塞同步模型,先产生windows消息,然后进行操作,操作不完成不返回
int WSAAsyncselect(
 SOCKET s,   //socket句柄
 HWND hWnd,   //指定接受消息的窗口句柄
 u_int wMsg,   //指定网络事件来到时接受到的消息ID
 long lEvent   //指定哪些网络事件需要通知
 );
 
lEvent可以取以下值的组合:
FD_READ  缓冲区有数据,可读
FD_WRITE 缓冲区变空,可写
FD_ACCEPT 有连接接入
FD_CONNECT 连接完成
FD_CLOSE socket连接关闭

LRESULT CALLBACK WindowProc(HWND hWnd,WPARAM wParam,LPARAM lParam);
wParam - socket 句柄
lParam - 高位错误代码,低位网络事件码;出错代码为0时,继续检查低位,确定网络事件

操作预定义:
#define WSAGETSELECTERROR(lParam) HIWORD(lParam) //高位错误码
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam) //低位通知码

评价:
于消息驱动融合在了一起,不再需要专用工作线程处理
也支持多个socket同时处理,只要调用WSAAsyncSelect时设置同个窗口句柄即可,但此方式整体性能不高

3、WSAEventSelect 模型
异步事件通知I/O模型,依靠事件对象句柄通知

非阻塞同步模型,先响应事件,然后进行操作,操作不完成不返回
int WSAEventSelect(
 SOCKET s,   //socket句柄
 WSAEVENT hEventObject,  //事件对象句柄
 long lNetworkEvents  //指定需要通知的网络事件
 );
 
WSAEVENT WSACreateEvent(void);  //创建手工重置的事件对象句柄

DWORD WSAWaitForMultipleEvents(
 DWORD cEvents,   //下面事件对象句柄数量
 const WSAEVENT* lphEvents, //事件对象句柄数组
 BOOL fWaitAll,   //是否等待所有事件变为受信状态
 DWORD dwTimeout,  //指定等待时间,WSA_INFINITE-无穷大
 BOOL fAlertable   //使用WSAEventSelect时可以忽略,设为false
 );
最多支持WSA_MAXIMUM_WAIT_EVENTS个事件对象,64个事件对象的限制,
多个事件受信时,WSAWaitForMultipleEvents返回最前一个的索引,
为了保持每个事件都得到处理,返回后要再对每个事件调用WSAWaitForMultipleEvents函数,测试状态.

一旦事件对象受信,调用WSAEnumNetworkEvents查看发生的网路事件
int WSAEnumNetworkEvents(
 SOCKET s,  //socket句柄
 WSAEVENT hEventObject, //对应的事件对象句柄.如果提供了,则会重置该事件对象状态
 LPWSANETWORKEVENTS lpNetworkEvents //指向结构的指针,函数返回的数据
 );
typedef struct _WSANETWORKEVENTS{
 long lNetworkEvent; //发生的网络事件,FD_READ等
 int iErrorCode[FD_MAX_EVENTS]; //错误代码,索引对应FD_READ,FD_ACCEPT 等
 );
 
评价:
收到64个socket的限制,需要工作线程在WSAWaitForMultipleEvents处等待
大量socket的情况需要使用线程池

4、重叠(Overlapped)I/O 模型
基于异步的多个socket管理模型,和前几个相比有更好的系统性能

非阻塞异步模型,先进行操作,立刻返回,而后根据事件判断操作是否完成

评价:
在大量异步socket系统中,使用此模型为佳

参考文献
windows网路与通讯程序设计(windows套接字I/O模型) 

猜你喜欢

转载自blog.csdn.net/skywoodsky/article/details/1526998