poll函数与select函数的功能基本一样,其定义如下:

#include <poll.h>

int poll(struct pollfd fds[], nfds_t nfds, int timeout);

参数说明:

struct pollfd{

  int fd;              //文件描述符

  short events;    //请求的事件

  short revents;   //返回的事件

  };

fds:是一个struct pollfd结构类型的数组,用于存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于 socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select() 函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因 此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况

nfds:nfds_t类型的参数,用于标记数组fds中的结构体元素的总数量;

timeout:是poll函数调用阻塞的时间,单位:毫秒;

poll() 函数不会受到socket描述符上的O_NDELAY标记和O_NONBLOCK标记的影响和制约,也就是说,不管socket是阻塞的还是非阻塞 的,poll()函数都不会收到影响;而select()函数则不同,select()函数会受到O_NDELAY标记和O_NONBLOCK标记的影 响,如果socket是阻塞的socket,则调用select()跟不调用select()时的效果是一样的,socket仍然是阻塞式TCP通讯,相 反,如果socket是非阻塞的socket,那么调用select()时就可以实现非阻塞式TCP通讯;

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<sys/wait.h> //*进程用的头文件*/
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<poll.h> //包含poll的头文件 #define MAXLINE 1024 //通信内容的最大长度 #ifndef FD_SETSIZE
#define FD_SETSIZE 25 //select最多能处理的文件描述符
#endif ssize_t readn(int fd, void *buf, size_t count)
{
ssize_t nleft=count;
ssize_t nread;
char *charbuf=(char*) buf; while(nleft>)
{
nread=read(fd,charbuf,nleft);
if(nread<)
{
if(errno==EINTR)
continue;
return -;
}
else if(nread==)
return count-nleft; charbuf +=nread;
nleft=count-nread;
}
return count;
} ssize_t writen(int fd, const void *buf, size_t count)
{
ssize_t nleft=count;
ssize_t nwrite;
char *charbuf=(char*) buf; while(nleft>)
{
nwrite=write(fd,charbuf,nleft);
if(nwrite<)
{
if(errno==EINTR)
continue;
return -;
}
else if(nwrite==)
return count-nleft;
charbuf +=nwrite;
nleft=count-nwrite; }
return count;
} ssize_t recv_peek(int sockfd, void *buf, size_t len)
{
int ret;
while()
{
ret=recv(sockfd,buf,len,MSG_PEEK);
if(ret==-&& errno==EINTR)
continue;
return ret;
}
} ssize_t readline(int sockfd, void *buf, size_t len)
{
ssize_t nleft=len,nread;
int ret;
char* bufchar=buf;
while()
{
ret=recv_peek(sockfd,bufchar,len);
if(ret<||ret==)
return ret;
nread=ret;
int i;
for(i=;i<nread;i++)
{
if(bufchar[i]=='\n')
{
ret=readn(sockfd,bufchar,i+);
if(ret!=i+)
exit(EXIT_FAILURE);
return ret;
}
}
if(nread>nleft)
exit(EXIT_FAILURE);
nleft-=nread;
ret=readn(sockfd,bufchar,nread);
if(ret!=nread)
exit(EXIT_FAILURE);
bufchar+=nread; }
return -; } int main()
{
int sock_fd,new_fd,fd;//sock_fd用于监听,new_fd用于连接
int maxi;
struct pollfd client[FD_SETSIZE];//用于存放客户端描述符
int nready;//检测到的事件数
struct sockaddr_in srv_addr;//服务器的地址信息
struct sockaddr_in client_addr;//客户机的地址信息
int i,size; //地址结构数据的长度
fd_set rset,allset;
char sendbuf[],recvbuf[];
memset(sendbuf,,sizeof(sendbuf));
memset(recvbuf,,sizeof(recvbuf)); /*创建套接字*/
sock_fd=socket(AF_INET,SOCK_STREAM,);//采用IPv4协议
if(sock_fd==-)
{
perror("creat socket failed");
exit();
} /*服务器地址参数*/
srv_addr.sin_family=AF_INET;
srv_addr.sin_port=htons();
srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&srv_addr.sin_zero,sizeof(struct sockaddr_in));//bzero位清零函数,将sin_zero清零,sin_zero为填充字段,必须全部为零 int on=; //表示开启reuseaddr
if(setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<) //打开地址、端口重用
perror("setsockopt"); /*绑定地址和端口*/
if(bind(sock_fd,(struct sockaddr*)&srv_addr,sizeof(struct sockaddr))==-)
{
perror("bind failed");
exit();
} /*设置监听模式,等待客户机的监听*/
if((listen(sock_fd,))==-)
{
perror("listen failed");
exit();
} int maxi=;
client[].fd=sock_fd; //将监听套接字放在数组中
client[].events=POOLIN; //感兴趣的事件为数据可读
for(i=;i<FD_SETSIZE;i++)
client[i].fd=-; //描述符为-1表示空闲 //使用poll实现并发服务器
while()
{
nready=poll(client,maxi+,-); //超时时间为-1,表示阻塞直到检测到事件
if(nready==-)
{
if(errno==EINTR) //因为信号中断退出
continue;
perror("select\n");
}
else if(nready==) //超时
{
continue;
} if(client[].revents & POLLIN) //监听套接口产生可读
{
size=sizeof(struct sockaddr_in);
new_fd=accept(sock_fd,(struct sockaddr*)&client_addr,&size); /*接受连接,采用非阻塞是的模式调用accep*/
if(new_fd==-)
{
perror("accept failed");
//continue;//restart accept when EINTR
} printf("server:got connection from IP= %s prot= %d \n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));//连接成功,打印客户机IP地址和端口号
/*char *inet_nota(struct sockaddr_in in);
头文件:
arpa/inet.h
Winsock2.h
参数:
一个网络上的IP地址
返回值:
如果正确,返回一个字符指针,指向一块存储着点分格式IP地址的静态缓冲区(同一线程内共享此内存);错误,返回NULL。
uint31_t ntohs(uint32_t net32bitvalue);
头文件:
#include<netinet/in.h>
把net32bitvalue有网络字节序转换为主机字节序。
*/
if(send(new_fd,"Hello client,I am 192.168.229.125!\n",,)==-) //192.168.229.125为子进程IP,可更改
perror("send failed");
for(i=;i<FD_SETSIZE;i++) //检测已连接套接字中是否有套接字产生 {
if(client[i].fd<)
                {
client[i].fd=new_fd; //将描述符保存在某一个空闲的位置
break;
}
if(i==FD_SETSIZE) //没有找到空闲的位置,即描述符个数达到上限
perror("too many client");
if(i>maxi)
maxi=i;
client[i].events=POLLIN;
if(--nready<=) //若检测到的套接口已经处理完,则继续用poll监听
continue;
} for(i=;i<=maxi;i++)
{
if((fd=client[i].fd)<)
continue;
if(client[i].revents & POLLIN) //连接套接口产生事件
{
memset(recvbuf,,sizeof(recvbuf));
if((n=readline(fd,recvbuf,MAXLINE))==)
{
printf("client closed\n");
close(fd);
client[i].fd=-;
}
else if(n==-)
perror("readline\n");
else
{
writen(fd,recvbuf,n);
fputs(recvbuf,stdout);
} if(--nready<=)
break;
}
} }
}

poll函数的更多相关文章

  1. linux poll函数

    poll函数与select函数差不多 函数原型: #include <poll.h> int poll(struct pollfd fd[], nfds_t nfds, int timeo ...

  2. poll()函数的使用

    分类: LINUX poll函数用于监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,若监测的任何一个事件发生,poll将唤醒睡眠的进程,并判断是什么等待事件发生,执行相应的操作.poll函 ...

  3. select与poll函数介绍

    select与poll函数介绍 在所有依从POSIX的平台上,select函数使我们可以执行I/O多路转接.传向select的参数告诉内核: 1)我们所关心的描述符 2)对于每个描述符我们所关心的状态 ...

  4. I/O多路复用——select函数与poll函数

    1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...

  5. poll函数和串口设置

    2015.1.24 今天星期六,多云,早晨8:17起床的,今天是来南京起床最迟的一天,因为昨晚睡得有点迟,今天又不用上课,整个人有点放松.收拾好来到教室,教室门没有开,胡明也到了,其他人还在宿舍睡觉, ...

  6. [转载] poll()函数

    原地址:http://baike.baidu.com/view/2997591.htm   poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函 ...

  7. I/O多路转接之poll 函数

    poll 一.poll()函数: 这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明: #include < ...

  8. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

  9. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

随机推荐

  1. mysql支持跨表delete删除多表记录

    前几天写了Mysql跨表更新的一篇总结,今天我们看下跨表删除. 在Mysql4.0之后,mysql开始支持跨表delete. Mysql可以在一个sql语句中同时删除多表记录,也可以根据多个表之间的关 ...

  2. jquery 获取和设置 checkbox radio 和 select option的值?

    ============== 获取和设置 checkbox radio 和 select的值? === val()函数, 其名字就表达了 它的意思: 他就是= value 的简写! val就是valu ...

  3. 使用/调用 函数的时候, 前面加不加 对象或 this?

    这个问题, 其实没有细想: 应该是这样的: (想明白了, 就会少很多困惑, 会对语言的把握 会 更深入更透彻) 任何一门 语言, (如果你自己去设计一门语言...). 都要规定 一些 "关键 ...

  4. jquery 清除动画队列不疑惑

    $(this).siblings().stop().fadeTo(200, 0.3); jquery动画存在一个队列, 会把事件产生的动画 放在一个队列中,当来不及执行这些事件队列的时候,会在事件结束 ...

  5. Linux下的特殊权限SetUID

    1.SetUID的功能 只有可以执行的二进制程序才能设置SUID权限 命令执行者要对改程序拥有x执行权限 命令执行者在执行改程序的时候获得该程序文件属主的身份(在执行程序的过程中灵魂附体为文件的属性) ...

  6. ESI 动态缓存技术

    任何一个Web网站的内容都是在不断更新和变化,但这并不意味这这个网站的内容就是动态内容,事实上,动态的内容是指用户每次点击 相同的链接时取的的内容是由Web服务器应用程序生成的,如常见得ASP,JSP ...

  7. AngularJS API之isXXX()

    Angular中保存了很多的判断方法,可以用来验证对象是否符合某种要求,详细的参考代码样例即可 <html> <head> <meta http-equiv=" ...

  8. 基础知识系列☞各版本下IIS请求处理过程区别

    转载地址→http://www.cnblogs.com/fsjohnhuang/articles/2332074.html ASP.NET是一个非常强大的构建Web应用的平台, 它提供了极大的灵活性和 ...

  9. POJ 1845 Sumdiv

    快速幂+等比数列求和.... Sumdiv Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12599 Accepted: 305 ...

  10. 2013nanjignB

    B - Poor Warehouse Keeper Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...