poll系统调用和select类似。也是在指定时间内轮询一定数量的文件描写叙述符,以測试当中是否有就绪者。poll和select效率差点儿相同,仅仅是其使用接口相对简单些,poll不在局限于1024个文件描写叙述符。poll监听事件和触发事件分开,event表示监听事件。revents表示触发的事件。

相比select不用每一次都须要又一次设置监听事件。

 #include <poll.h>

 int poll(struct pollfd *fds, nfds_t nfds, int timeout);
//第一个參数是struct pollfd数组
struct pollfd
{
int   fd;   /* file descriptor */你要监控文件描写叙述符
     short events;   /* requested events */ 监听文件描写叙述符上的事件 传入參数由用户设置
     short revents;    /* returned events */监控文件描写叙述符事件返回值 传出參数由内核设置
}; POLLIN普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
POLLRDNORM-数据可读
POLLRDBAND-优先级带数据可读
POLLPRI 高优先级可读数据
POLLOUT普通或带外数据可写
POLLWRNORM-数据可写
POLLWRBAND-优先级带数据可写
POLLERR 错误发生
POLLHUP 发生挂起
POLLNVAL 描写叙述字不是一个打开的文件 第二个參数。指结构体数组长度。
timeout 毫秒级等待
-1:堵塞等,#define INFTIM -1 Linux中未定义此宏
0:马上返回。不堵塞进程
>0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值

poll server端实例:

#include<stdio.h>
#include<string.h>
#include<poll.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<errno.h>
#define OPEN_MAX 1024 int create_listen(int port)
{
int listen_st,on;
struct sockaddr_in s_addr;
listen_st =socket(AF_INET,SOCK_STREAM,0);
if(listen_st==-1) {
perror("socket error ");
return -1;
}
if(setsockopt(listen_st,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==-1)
{
perror("setsockopt error");
return -1;
}
s_addr.sin_port=htons(port);
s_addr.sin_family=AF_INET;
s_addr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(listen_st,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in))==-1)
{
perror("bind error");
return -1;
}
if (listen(listen_st, 5) == -1) // 设置文件描写叙述符具有监听的功能
{
perror("listen error");
return -1;
}
return listen_st;
} int run_server(int port)
{
int i,maxi,listen_st,conn_st,sockaddr_len;
int nready;
struct pollfd client[OPEN_MAX];
char buf[1024];
struct sockaddr_in c_addr;
listen_st=create_listen(port);
if(listen_st==-1)
{
return -1;
}
for(i=1;i<OPEN_MAX;i++)
{
client[i].fd=-1;
}
client[0].fd=listen_st;
client[0].events=POLLIN;
maxi=0;
while(1)
{
nready = poll(client,maxi+1,-1);//poll 堵塞
if(nready<0)
{
perror("poll error");
break;
}
if((client[0].revents&POLLIN))//检測listen_st
{
sockaddr_len=sizeof(c_addr);
conn_st=accept(listen_st,(struct sockaddr *)&c_addr,&sockaddr_len);
printf("received form %s at port:%d \n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));
for(i=0;i<OPEN_MAX;i++)
{
if(client[i].fd<0)
{
client[i].fd=conn_st;
client[i].events=POLLIN;
break;
}
}
if(i==OPEN_MAX)
{
printf("too many client \n");
close(conn_st);
}else
{
if(i>maxi) //记录最大下标
{
maxi=i;
}
}
if(--nready==0) continue;
} for(i=1;i<=maxi;i++)
{
if((conn_st=client[i].fd)<0)
{
continue;
} if(client[i].revents&POLLIN)
{
memset(buf,0,sizeof(buf));
int rv=read(conn_st,buf,sizeof(buf));
if(rv<0)
{
if(errno==ECONNRESET)/* 当收到RST标志时*/
//这样的错误是因为客户端发过FIN ACk掉线了客服端进程已经结束了 服务端再发FIN 客户端会发送RST
{
printf("client aborted connection \n");
close(conn_st);
client[i].fd=-1;
}
}
else if(rv==0)
{
printf("close client \n");
close(conn_st);
client[i].fd=-1;
}
else
{
printf("recv from client:%s \n",buf);
write(conn_st,buf,strlen(buf));
}
if (--nready == 0) break; //就绪个数减一
} }
}
close(listen_st);
return 0;
} int main(int argc,char *argv[])
{
if(argc<2)
{
printf("usage:%s port \n",argv[0]);
return 0;
}
int port=atoi(argv[1]);
if(port==0)
{
printf("port error \n");
return 0;
}
printf("start server \n");
run_server(port);
return 0;
}

多路转接模型之poll的更多相关文章

  1. I/O多路转接模型

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  2. IO多路转接select和poll

    select IO多路复用的设置方法与信号的屏蔽有点相似: 信号屏蔽需要先设定一个信号集, 初始化信号集, 添加需要屏蔽的信号, 然后用sigprocmask设置 IO多路转接需要先设定一个文件描述符 ...

  3. UNIX环境高级编程——I/O多路转接(select、pselect和poll)

    I/O多路转接:先构造一张有关描述符的列表,然后调用一个函数,直到这些描述符中的一个已准备好进行I/O时,该函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.pselect ...

  4. 【Nginx】I/O多路转接之select、poll、epoll

    当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...

  5. 高级I/O之I/O多路转接——pool、select

    当从一个描述符读,然后又写到另一个描述符时,可以在下列形式的循环中使用阻塞I/O: ) if (write(STDOUT_FILENO, buf, n) != n) err_sys("wri ...

  6. I/O多路转接 --- UNIX环境高级编程

    I/O多路转接技术:先构造一张有关描述符的列表,然后调用一个函数,知道这些描述符中的一个已准备好进行I/O时,给函数才返回.在返回时,它告诉进程哪些描述符已准备好可以进行I/O. poll.selec ...

  7. Linux下I/O多路转接之epoll(绝对经典)

    epoll 关于Linux下I/O多路转接之epoll函数,什么返回值,什么参数,我不想再多的解释,您不想移驾,我给你移来: http://blog.csdn.net/colder2008/artic ...

  8. Linux下I/O多路转接之select --fd_set

    fd_set 你终于还是来了,能看到这个标题进来的,我想,你一定是和我遇到了一样的问题,一样的疑惑,接下来几个小时,我一定竭尽全力,写出我想说的,希望也正是你所需要的: 关于Linux下I/O多路转接 ...

  9. select函数与I/O多路转接

    select函数与I/O多路转接 相作大家都写过读写IO操作的代码,例如从socket中读取数据可以使用如下的代码: while( (n = read(socketfd, buf, BUFSIZE) ...

随机推荐

  1. 关于AMAZON SES设置的一些要点

    1.首先要有一个企业邮箱,如果没有可以去腾讯(http://exmail.qq.com/onlinesell/intro)申请一个,网易也有,不过解析几次搞了两天都是未通过,腾讯几分钟就好了 企业邮箱 ...

  2. Webpack 入门(一):安装 / 打包 / 命令行

    一:安装webpack和基本环境搭建 新建一个工作的文件夹(我取的名字叫Webpack) 打开命令行,cd进入该文件夹 //初始化一下npm > E:\work\Webpack>npm i ...

  3. numpy调试

    x1 = np.arange(9.0) 结果就是: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.]) 拿这个来初始化进行调试

  4. bash基础——管道符、通配符

    1.多命令顺序执行 多命令顺序执行 格式 作用 ; 命令1 ; 命令2 多个命令之间没有任何逻辑联系 && 命令1&&命令2 逻辑与 当命令1正确执行,则命令2才会执行 ...

  5. returnFloat_thousand() 以万计数 ,如100,结果是0.01

    function returnFloat_thousand(value){ var value=Math.ceil(Math.round(parseFloat(value)*100)/100)/100 ...

  6. 指针函数(Pointer Function)和函数指针(Pointer to Function或Function Pointer)

    一.指针函数 1.解释:指针函数很好理解:简单来说,就是一个返回指针的函数,本质是一个函数.如: int fun(int x,int y);    //这是一个普通函数的声明,返回值是一个int类型, ...

  7. 黑马毕向东Java基础知识总结

    Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记    侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...

  8. mui.openWindow的html5+和web传参的兼容

    mui.openWindow兼容web&plus环境下的页面传参 背景介绍 刚刚好要写个微信公众号和html5+兼容的项目 发现总是用localStorage传参不是事啊 太不优雅了 想了想还 ...

  9. 3.2.8 sed 的运作

        sed 的工作方式相当直接.命令行上的每个文件会依次打开与读取.如果没有文件,则使用标准输入,文件名“-”(单个破折号)可用于表示标准输入.       [many@avention Desk ...

  10. 如何用nfs命令烧写内核和文件系统(网络下载文件到nandflash)(未完)

    使用tftp下载烧写 a.设uboot里的ip地址 set ipaddr 192.168.1.17(uboot的ip设置成同网段) set serverip 192.168.1.5(电脑本机作为服务i ...