一:注意
1.socket上接收到普通数据和外带数据都将使select返回但是socket处于的是不同的状态。前者处于可读状态,后者处于异常状态。
对于接受到普通数据时:int connfd=accept(listenfd,(struct sockaddr*)&client_address,&client_addrlength);
If(FD_ISSET(connfd,&read_fds)){
Recv(connfd,buf,sizeof(buf)-1,0) //普通的读取数据方式
}
If(FD_ISSET(connfd,&exception_fds)){
Recv(connfd,buf,sizeof(buf)-1,MSG_OOB) //对于异常事件,采用带MSG_OOB标志的recv函数读取外带数据
}
select中:会有一个数组和一个集合,数组用来存放所有监听的文件描述符,当有关注的事件发生的时候,将发生事件的文件描述符保存到对应的事件集合中,再将该集合最终拷贝到内核中,由内核处理。
而epoll则是将感兴趣的事件注册到内核事件表中,当有注册的事件发生时,内核就会将该事件的所对应的文件描述符加入到就绪队列中
2.FD_SETSIZE指定能容纳文件描述符的数量
3.select的第三个参数timeout,是用来设置select函数的超时时间,是一个timeval结构类型的指针,采用指针参数是因为内核将修改它以告诉应用程序等待了多久。但是select调用返回后的timeout值不能完全准确,比如调用失败的时候timeout的值是不确定的。
timeval提供了秒级和微秒级别的定时方式。当给它的两个参数都设为0时select就会立即返回.如果给timeout传NULL则select将会一直阻塞直到某个文件描述符就绪。
4.应用程序调用select函数时,通过将readfds,writefds,exceptfds传入自己感兴趣的文件描述符。传入的文件描述符是在对应的事件集合中,当select调用返回时,内核将修改这些感兴趣的事件的相应位来通知应用程序哪些文件描述符已经就绪