正文

转socket非阻塞模型2008-08-24 11:09:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/sword2008/37837.html

分享到:

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

阅读(3523) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册