文章标题
来源:互联网 发布:mac系统被删除了 编辑:程序博客网 时间:2024/05/24 07:32
浅谈三大常用的多路I/O转接模型之一:select
select
函数介绍:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);返回:若有描述符准备就绪返回已准备就绪的描述符个数, 若超时则为0,若出错则返回-1. fd_set可以理解为是一个集合类型,如{1,2,3}。struct timeval {long tv_sec; // 秒 (struct timeval结构体可以理解long tv_usec; // 微妙 成是一个定时器)};
参数详解:
nfds: select等待的最大描述符个数,其值为被等待的最大描述符的
值加1(maxfd + 1),因为描述符是从0开始的,当有一个描述符
时,其个数为1,以此类推,所以是(maxfd + 1)。
readfds: 该参数被设置,则是让内核测试读的描述符
writefds: 该变量如果被设置,则是让内核测试写的描述符
exceptfds: 该变量被设置,则是让内核测试异常的描述符参数中的三个fd_set参数通常是一个数组,其中每个成员都是一个描述符,
一般与select配套使用的是四个宏:void FD_ZERO(fd_set *set); // 把集合中的每一位清0;
void FD_SET(int fd, fd_set *set); // 把描述符fd加入集合set中;
void FD_CLR(int fd, fd_set *set); // 把描述符fd从集合set中删除;
void FD_ISSET(int fd, fd_set *set); // select返回时,检测时候是fd返回select模型有个特定,每当select返回后,要想再进入阻塞状态,参数需要重新设置,所以,我们应该用一个数组来保存每次的描述符。为了便于理解我用一幅简单的图来表示select模型。
select模型常规使用方法:(为了精简代码,错误处理就不写了)
// 头文件 省略
define SA struct sockaddr_in
define MAXSIZE 1024 // 缓冲区最大值
int main(int argc, char* argv[]) {
int sockfd, listenfd, connfd;
int nready, maxfd, maxi, i, n, client[MAXSIZE];
SA sv_addr;
socklen_t sv_len;
fd_set rset, allset;
char sendline[MAXSIZE];
listenfd = sockfd(AF_INET, SOCK_STREAM, 0);sv_len = sizeof(sv_addr);bzero(&sv_addr, sv_len); // 结构体清零sv_addr.sin_family = AF_INET;sv_addr.sin_port = htons(atoi(argv[1]));sv_addr.sin_addr.s_addr = htonl(INADDR_ANY);bind(listenfd, (SA*)(&sv_addr),sv_len);listen(listenfd, 128);FD_ZERO(&allset);FD_SET(listenfd, &allset);for (i = 0; i < MAXSIZE; ++i)client[i] = -1; // 初始化为-1maxi = 0;maxfd = listenfd;for ( ; ; ) {rset = allset; nready = select(maxfd + 1, &rset, NULL, NULL, NULL); if (FD_ISSET(listenfd, &rset)) { connfd = accept(listenfd, (SA*)(&sv_addr), &sv_len); for (i = 0; i < MAXSIZE; ++i) { if (client[i] < 0) { client[i] = connfd; break; } } if (i >= MAXSIZE) exit(EXIT_FAILURE); FD_SET(connfd, &allset); if (i > maxi) maxi = i; if (--nready == 0) continue;}for (i = 1; i <= maxi; ++i) { if ( (connfd = client[i]) < 0)) continue; n = read(connfd, sendline, MAXSIZE); write(connfd, sendline, n); if (--nready == 0) break;}}close(listenfd);return 0;
}
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- leetcode-66 Plus One
- 不使用Cygwin,在eclipse中快速开发JNI,一键生成C头文件.h,以及一键使用NDK交叉编译
- 黑马程序员——Java基础——集合(三)
- 关于prim算法的讨论:例:HDOJ1233——还是畅通工程
- (大数据之hadoop)hadoop2.2.0集群搭建
- 文章标题
- 结合prototype封装自定义的HashMap
- IOS两个App应用之间的跳转
- (大数据之hadoop)hadoop2.4.1集群搭建
- 几种软件滤波算法的原理和比较
- Android:wpa_supplicant决定选择哪种驱动
- id ,NSObject, id<NSObject>区别
- 页面中有<tbody>标签,自以为是更好的规范<table>标签的
- 模拟新浪微博随便看看