Select在echo_server中的用法
Select原型理解:
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);
1、fd_set*readfds 是指向fd_set结构的指针,我们关心这个集合中的文件描述符是否可读,文 件描述符可读的条件:
1、 socket接收缓冲区中的数据量大于或等于当前缓冲区的低水位线.此时对于read操作不会 被阻塞并且返回一个正值(读取的字节数).低水位线可以通过SO_RCVLOWAT选项设定,对 于Tcp和Udp来说其默认值为1.
2、socket连接的读端被关闭,如shutdown(socket, SHUT_RD)或者close(socket).对应底层 此时会接到一个FIN包,read不会被阻塞但会返回0.代表读到socket末端.
3、socket是一个监听socket并且有新连接等待.此时accept操作不会被阻塞.
4、发生socket错误.此时read操作会返回SOCKET_ERROR(-1).可以通过errno来获取具体错 误信息.
2、fd_set*writefds是指向fd_set结构的指针,我们关心这个集合中的文件描述符是否可写,文 件描述符可写的条件:
1、socket发送缓冲区中的可用缓冲大小大于或等于发送缓冲区中的低水位线并且满足以下条件之一
(1)、socket已连接
(2)、socket本身不要求连接,典型如Udp
低水位线可以通过SO_SNDLOWAT选项设置.对于Tcp和Udp来说一般为2048.
2、socket连接的写端被关闭,如shutdown(socket, SHUT_WR)或者close(socket).在一个已 经被关闭写端的句柄上写数据会得到SIGPIPE的信号(errno).
3、一个非阻塞的connect操作连接成功 或者 connect操作失败.
4、发生socket错误.此时write操作会返回SOCKET_ERROR(-1).可以通过errno来获取具体错误信息.
3、timeout:
timeout == NULL, 等待无线长时间
timeout == 0; 不等待
timeout > 0; 等待指定的时间
4、fd_set是通过位图来表示socket的状态,因此select可监控的文件描述符的个数取决于sizeof(fd_set) * 8的值,如下说明引用http://blog.youkuaiyun.com/lingfengtengfei/article/details/12392449中的说明
理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd。
(1)执行fd_set set;FD_ZERO(&set);则set用位表示是0000,0000。
(2)若fd=5,执行FD_SET(fd,&set);后set变为0001,0000(第5位置为1)
(3)若再加入fd=2,fd=1,则set变为0001,0011
(4)执行select(6,&set,0,0,0)阻塞等待
(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。