select示例
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, const struct timeval * timeout);
ndfs:select监视的文件句柄数,视进程中打开的文件数而定,一般设为要监视各文件中的最大文件描述符值加1。
readfds:这个文件描述符集合监视文件集中的任何文件是否有数据可读,当select函数返回的时候,readfds将清除其中不可读的文件描述符,只留下可读的文件描述符。
writefds:这个文件描述符集合监视文件集中的任何文件是否有数据可写,当select函数返回的时候,writefds将清除其中不可写的文件描述符,只留下可写的文件描述符。
exceptfds:这个文件集将监视文件集中的任何文件是否发生错误,其实,它可用于其他的用途,例如,监视带外数据OOB,带外数据使用MSG_OOB标志发送到套接字上。当select函数返回的时候,exceptfds将清除其中的其他文件描述符,只留下标记有OOB数据的文件描述符。
timeout:本次select()的超时结束时间。这个参数至关重要,它可以使select处于三种状态:
(1)若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;
(2)若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;
(3)timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。
函数的返回值:
正值:表示监视的文件集中有文件描述符符合要求
零值:表示select监视超时
负值:表示发生了错误,错误值由errno指定。
宏操作:
FD_ZERO(fd_set *set): 用来清除描述词组set的全部位
FD_SET(int fd,fd_set*set): 用来设置描述词组set中相关fd的位
FD_ISSET(int fd,fd_set *set): 用来测试描述词组set中相关fd 的位是否为真
FD_CLR(inr fd,fd_set* set): 用来清除描述词组set中相关fd 的位
注意事项:
(1)对于可写性的检查,最好放在需要写数据的时候进行检查。如果和可读性放在同一个地方进行检查,那么select很可能每次都会因为可写性检查成功而返回。
(2)select()调用会清空传递给它的集合参数中的内容,也就是会清空readfds、writefd、exceptfds这三个指针参数所指定的描述符集合。因此,在每次调用select()之前,必须重新初始化并把需要监视的描述符填写到相应的描述符集合中。select()调用也会清空timeout指针所指向的struct timeval结构,所以在每次调用select()之前也要重新填充timeout指针所指向的struct timeval结构。
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_FD 1024
volatile int max = -1;
int listenfd ;
char buf[1024];
fd_set read_fds;
fd_set exception_fds;
int sel_fd_arr[MAX_FD];
int get_max_fd(){
int i;
for (i = MAX_FD-1; i >= 0; i--)
if (sel_fd_arr[i] == 0)
return i;
return -1;
}
void set_sel_events(){
int i;
for (i = 0; i < MAX_FD; i++)
if (sel_fd_arr[i] == 0){
FD_SET(i, &read_fds);
FD_SET(i, &exception_fds);
}
}
void * sel_thread_fun(void * arg){
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
char addr_p[16];
int i = 0;
printf("sel_thread_fun begin\n");
while(1){
max = get_max_fd();
printf("max=%d\n", max);
int ret = select(max+1, &read_fds, NULL, &exception_fds, NULL);
if (ret < 0){
printf("selection failure \n");
continue;
}
for (i = 0; i < max+1; i++){
memset(buf, 0x00, sizeof(buf) );
if (FD_ISSET(i, &read_fds)){
if (i == listenfd){
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
printf("connection from %s \n", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
if ( connfd < 0){
printf("errno is %d\n", errno);
close(listenfd);
}
sel_fd_arr[connfd] = 0;
}
else{
ret = recv(i, buf, sizeof(buf)-1, 0);
if (ret <= 0){
printf("recv ret=%d\n", ret);
sel_fd_arr[i] = -1;
break;
}
printf("get %d bytes of normal data:%s\n", ret, buf);
}
}
else if( FD_ISSET(i, &exception_fds) ){
ret = recv(i, buf, sizeof(buf)-1, MSG_OOB);
if (ret <= 0){
sel_fd_arr[i] = -1;
break;
}
printf("get %d bytes of oob data:%s\n", ret, buf);
}
}
set_sel_events();
}
return (int*)(1) ;
}
int main(int argc, char *argv[]){
if (argc <= 2){
printf("usage:%s ip_address port_number \n", argv[0]);
return 1;
}
int i;
for (i = 0; i < MAX_FD; i++)
sel_fd_arr[i] = -1;
char addr_p[16];
const char *ip = argv[1];
int port = atoi(argv[2]);
int ret = 0;
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
listenfd = socket(PF_INET, SOCK_STREAM, 0);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address) );
assert(ret != -1);
ret = listen(listenfd, 5);
assert(ret != -1);
FD_ZERO(&read_fds);
FD_ZERO(&exception_fds);
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
sel_fd_arr[listenfd] = 0;
FD_SET(listenfd, &read_fds);
FD_SET(listenfd, &exception_fds);
pthread_t thd;
pthread_create(&thd, NULL, sel_thread_fun, NULL);
pthread_join(thd, NULL);
/*
while(1){
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
printf("connection from %s \n", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
if ( connfd < 0){
printf("errno is %d\n", errno);
close(listenfd);
}
if ( connfd > max)
max = connfd;
FD_SET(connfd, &read_fds);
FD_SET(connfd, &exception_fds);
}
*/
close(listenfd);
return 0;
}
select示例的更多相关文章
- 基础SELECT示例掌握
SELECT查询语句 ---进行单条记录.多条记录.单表.多表.子查询-- SELECT [ALL | DISTINCT | DISTINCTROW ] [HIGH_PRIORITY] [MAX_ST ...
- 批量插入数据insert into select示例
//增加 $addSql =" insert into hxqc_auth_group_limits(group_id,company_id)"; foreach ($add_da ...
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例
除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnblogs.com/Anker/p/3265058.html 最简单的select示例: #incl ...
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例【转】
转自:https://www.cnblogs.com/welhzh/p/4950341.html 除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnb ...
- IO多路复用:select、poll、epoll示例
一.IO多路复用 所谓IO多路复用,就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作. Linux支持IO多路复用的系统调用有 ...
- SQL指南-SELECT语句
SELECT 语句 SELECT 语句用于从表中筛选数据.列表结果存储于一个结果表中(称作result-set) 语法 SELECT column_name(s)FROM table_name 注意: ...
- python select epoll poll的解析
select.poll.epoll三者的区别 select select最早于1983年出现在4.2BSD中,它通过一个select()系统调用来监视多个文件描述符的数组(在linux中一切事物皆文件 ...
- js jquery select 操作 获取值,选中选项,增加,修改,删除
select示例: <select id="sel"> <option value="1">one</option> < ...
- I/O复用——select和poll
概述 I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写 ...
随机推荐
- [Luogu] 染色
https://www.luogu.org/problemnew/show/P2486 qizha 为什么会wa #include <cstdio> #include <cmath& ...
- Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(困难版) 并查集
题意 给一个$ n \times m$ 的网格,每个格子里有一个数字,非 \(0\) 即 \(1\),行从上往下依次编号为 \(1, 2, \cdots, n\),列从左往右依次编号为 \(1, 2, ...
- 最简单的babel+webpack配置
首先先介绍一下2个重要的库:core-js 和 regenerator core-js core-js 是用于 JavaScript 的组合式标准化库,它包含 es5 (e.g: object.fre ...
- NSString的创建
create #progma mark create NSString void stringCreate(){ //char *s="A String";->c NSSt ...
- 微信小程序之简单记账本开发记录(六)
昨天虽然将页面成功的搭建出来 但是其中的增删改查功能没有实现,需要到逻辑页面,即js页面注册一下 效果如下图
- HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)
和前几天做的AC自动机类似. 思路简单但是代码200余行.. 假设solve_sub(i)表示长度为i的不含危险单词的总数. 最终答案为用总数(26^1+26^2+...+26^n)减去(solve_ ...
- DLL:操作数据库和表
1. 操作数据库 C(Create 创建) R(Retrieve 查询) U(Update 更新) D(Delete 删除) (1) 查询数据库 1) 查询所有数据库名称 SHOW DATABASES ...
- Python下划线命名模式
- PHP学习之文件上传类
<?php $up = new Upload(); $newPath = $up->uploadFile('fm'); if ($newPath === false) { var_dump ...
- 图像分割-Mask Scoring R-CNN
转载:https://zhuanlan.zhihu.com/p/58291808 论文链接:https://arxiv.org/abs/1903.00241 代码链接:https://github.c ...