Select模型的学习

来源:互联网 发布:torch软件下载 编辑:程序博客网 时间:2024/06/05 13:13

1、套接字分为两种状态:阻塞和非阻塞态,可以使用ioctlsocket函数来设置FIONBIO指定套接字状态。对套接字进行recv时,在阻塞时,返回值大于0,表示有数据收到;返回值等于0,表示对方关闭连接;返回值为-1,表示连接意外中断(RST)。而在非阻塞时返回值如果为-1,可能表示这次没有收到数据。此时需要判断WSAGetLastError是否是WSAEWOULDBLOCK,是的话表示当前无数据,需要等待下一次接收。

    Microsoft Windows是非抢先的多任务环境,如果一个应用程序不主动放弃其控制权,别的应用程序就不能够执行。因此,在Windows Sockets网络程序设计中,尽管它支持阻塞操作,但是它是反对使用阻塞操作的。在Windows Sockets实现中,对于不能立即完成的阻塞操作做如下处理:DLL初始化操作,然后进入一个循环。在循环中,它发送任何Windows消息,并检查这个Windows Sockets调用是否完成,在必要时,它可以放弃CPU让其它应用程序执行。

2、select模型的基本思想就是轮询机制。首先初始化队列(把需要管理的套接字放入三个队列:读/写/意外队列),之后使用一定的超时值来进行查询(通过设置select函数的最后一个参数),然后再依次判断需要管理的套接字是否还在这三个队列中,如果能够在这三个队列中找到,那么就可以进行相应的处理。

3、select使用超时机制,通过设置该函数的最后一个参数(指向timeval结构体的指针),可以实现阻塞和非阻塞等状态。当该指针为NULL的时候,既是阻塞模式。当该指针指向的结构体的两个成员都设置为0时,既是非阻塞模式。使用超时查询时,一旦有套接字满足条件,即返回,返回值只满足条件的套接字的个数。返回0时表示超时时间到,仍旧没有满足条件的套接字。

4、使用select管理多个套接字的时候,请先把套接字设置为非阻塞模式,否则使用select模型基本没有任何效果。另外,使用select需要程序员统一管理每个套接字。并发服务(多进程/线程)的每个线程一般只对应一个套接字,不需要统一管理。

5、select管理的队列(读/写/意外队列)的格式如下:

typedef struct fd_set {
u_int fd_count;
SOCKET fd_array[FD_SETSIZE];

} fd_set;

其中FD_SETSIZE默认是64个。这个默认值可以修改,只需在包含Winsock2.h定义这个值即可。对这个队列的操作有四个宏:FD_CLR(从队列中清楚某个套接字)、FD_ISSET(判断某套接字是不是存在队列中)、FD_SET(把某套接字放入队列中)、FD_ZERO(把队列清空为0)。

6、套接字统一管理要点:使用动态变化的数组来存储所有需要管理的套接字,如借助STL中某些模板类,使得在查询的时候更快。对处理过的套接字进行计数,当计数达到select的返回值的时候,便跳出循环进行下一次的select。

7、不同情况时的处理方式:当某个套接字存在于

Readfds队列:

    之前该套接字被监听,并且有一个新的连接到来,那么此时accept可以成功。

    套接字上有数据可以接收(如果指定了SO_OOBINLINE,那么此时可以接受带外数据)

    连接被关闭/重置/断开。

Writefds队列:

    如果这个套接字(非阻塞)之前调用了connect函数,那么连接建立成功。

    数据可以发送了。

Exceptfds队列:

    如果这个套接字(非阻塞)之前调用了connect函数,那么连接建立失败。

    带外数据可以接收(没有指定SO_OOBINLINE)

原创粉丝点击