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系统中,使用此模型为佳
评论