http://zixiaoruixue731.blog.163.com/blog/static/336606020085253855750/
Winsock提供了两种套接字模式:锁定和非锁定.当我们使用锁 定套接字的时候,我们使用的很多函数,例如accpet,send,recv等等,
如果没有数据需要处理,这些函数都不会返回,也就是说,你的应用程 序会阻塞在那些函数的调用处.而 如果使用非阻塞模式,调用这些函 数,不管你有没有数据到达,他都会返回,所以,有可能我们在非阻塞 模式里,调用这些函数大部分的情况下会返回失败,所以就需要我们来处理很多的意外出错.
这显然不是我们想要看到的情况.我们可以采用Winsock的通讯模型 来避免这些情况的发生。
Winsock提供了五种套接字I/O模型来解决这些问题.他们分别是
select(选择),WSAAsyncSelect(异步选择), WSAEventSelect (事件选择), overlapped(重叠) ,completion
port(完成端口) .
我们在这里详细介绍一下select,WSAASyncSelect两种模型.
select模型是最常见的I/O模型.
使用
int select( int nfds , fd_set FAR* readfds , fd_set FAR* writefds , fd_set FAR* exceptfds ,
const struct timeval FAR * timeout ) ;
函数来检查你要调用的socket套接字是否已经有了需要处理的数据.
select包含三个socket队列,分别代表: readfds ,检查可读性,writefds,检查可写性,exceptfds,例外数据. timeout是select函数的返回时间.
例如,我们想要检查一个套接字是否有数据需要接收,我们可以把套 接字句柄加入可读性检查队列中,然后调用select,如果,该套接字没 有数据需要接收,select函数会把该套接字从可读性检查队列中删除 掉,所以我们只要检查该套接字句柄是否还存在于可读性队列中,就 可以知道到底有没有数据需要接收了.
Winsock提供了一些宏用来操作套接字队列fd_set.
FD_CLR( s,*set) 从队列set删除句柄s.
FD_ISSET( s, *set) 检查句柄s是否存在与队列set中.
FD_SET( s,*set )把句柄s添加到队列set中.
FD_ZERO( *set ) 把set队列初始化成空队列.
WSAAsyncSelect(异步选择)模型:
WSAASyncSelect模型就是把一个窗口和套接字句柄建立起连接,套接
字的网络事件发生时时候,就会把某个消息发送到窗口,然后可以在
窗口的消息响应函数中处理数据的接收和发送.
int WSAAsyncSelect( SOCKET s, HWND hWnd , unsigned int wMsg , long lEvent ) ;
这个函数可以把套接字句柄和窗口建立起连接,
wMsg 是我们必须自定义的一个消息.
lEvent就是制定的网络事件.包括FD_READ , FD_WRITE , FD_ACCEP t , FD_CONNECT , FD_CLOSE .
几个事件.
例如,我需要接收FD_READ , FD_WRITE , FD_CLOSE 的网络事件.可 以调用
WSAAsyncSelect( s , hWnd , WM_SOCKET , FD_READ | FD_WRITE | FD_CLOSE ) ;
这样,当有FD_READ , FD_WRITE 或者 FD_CLOSE网络事件时,窗口hWnd将会收到WM_SOCKET消息,消息参数的lParam标志了是什么事件 发生.