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

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

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

poll server端实例:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<poll.h>
  4. #include <sys/un.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include<errno.h>
  10. #define OPEN_MAX 1024
  11.  
  12. int create_listen(int port)
  13. {
  14. int listen_st,on;
  15. struct sockaddr_in s_addr;
  16. listen_st =socket(AF_INET,SOCK_STREAM,0);
  17. if(listen_st==-1)
  18.  
  19. {
  20. perror("socket error ");
  21. return -1;
  22. }
  23. if(setsockopt(listen_st,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==-1)
  24. {
  25. perror("setsockopt error");
  26. return -1;
  27. }
  28. s_addr.sin_port=htons(port);
  29. s_addr.sin_family=AF_INET;
  30. s_addr.sin_addr.s_addr=htonl(INADDR_ANY);
  31.  
  32. if(bind(listen_st,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in))==-1)
  33. {
  34. perror("bind error");
  35. return -1;
  36. }
  37. if (listen(listen_st, 5) == -1) // 设置文件描写叙述符具有监听的功能
  38. {
  39. perror("listen error");
  40. return -1;
  41. }
  42. return listen_st;
  43. }
  44.  
  45. int run_server(int port)
  46. {
  47. int i,maxi,listen_st,conn_st,sockaddr_len;
  48. int nready;
  49. struct pollfd client[OPEN_MAX];
  50. char buf[1024];
  51. struct sockaddr_in c_addr;
  52. listen_st=create_listen(port);
  53. if(listen_st==-1)
  54. {
  55. return -1;
  56. }
  57. for(i=1;i<OPEN_MAX;i++)
  58. {
  59. client[i].fd=-1;
  60. }
  61. client[0].fd=listen_st;
  62. client[0].events=POLLIN;
  63. maxi=0;
  64. while(1)
  65. {
  66. nready = poll(client,maxi+1,-1);//poll 堵塞
  67. if(nready<0)
  68. {
  69. perror("poll error");
  70. break;
  71. }
  72. if((client[0].revents&POLLIN))//检測listen_st
  73. {
  74. sockaddr_len=sizeof(c_addr);
  75. conn_st=accept(listen_st,(struct sockaddr *)&c_addr,&sockaddr_len);
  76. printf("received form %s at port:%d \n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));
  77. for(i=0;i<OPEN_MAX;i++)
  78. {
  79. if(client[i].fd<0)
  80. {
  81. client[i].fd=conn_st;
  82. client[i].events=POLLIN;
  83. break;
  84. }
  85. }
  86. if(i==OPEN_MAX)
  87. {
  88. printf("too many client \n");
  89. close(conn_st);
  90. }else
  91. {
  92. if(i>maxi) //记录最大下标
  93. {
  94. maxi=i;
  95. }
  96. }
  97. if(--nready==0) continue;
  98. }
  99.  
  100. for(i=1;i<=maxi;i++)
  101. {
  102. if((conn_st=client[i].fd)<0)
  103. {
  104. continue;
  105. }
  106.  
  107. if(client[i].revents&POLLIN)
  108. {
  109. memset(buf,0,sizeof(buf));
  110. int rv=read(conn_st,buf,sizeof(buf));
  111. if(rv<0)
  112. {
  113. if(errno==ECONNRESET)/* 当收到RST标志时*/
  114. //这样的错误是因为客户端发过FIN ACk掉线了客服端进程已经结束了 服务端再发FIN 客户端会发送RST
  115. {
  116. printf("client aborted connection \n");
  117. close(conn_st);
  118. client[i].fd=-1;
  119. }
  120. }
  121. else if(rv==0)
  122. {
  123. printf("close client \n");
  124. close(conn_st);
  125. client[i].fd=-1;
  126. }
  127. else
  128. {
  129. printf("recv from client:%s \n",buf);
  130. write(conn_st,buf,strlen(buf));
  131. }
  132. if (--nready == 0) break; //就绪个数减一
  133. }
  134.  
  135. }
  136. }
  137. close(listen_st);
  138. return 0;
  139. }
  140.  
  141. int main(int argc,char *argv[])
  142. {
  143. if(argc<2)
  144. {
  145. printf("usage:%s port \n",argv[0]);
  146. return 0;
  147. }
  148. int port=atoi(argv[1]);
  149. if(port==0)
  150. {
  151. printf("port error \n");
  152. return 0;
  153. }
  154. printf("start server \n");
  155. run_server(port);
  156. return 0;
  157. }

多路转接模型之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. AIX RAC 安装失败完全卸载

    1,删除软件安装目录 rm -rf /u01/app 2,删除以下目录内容 rm -rf/tmp/.oracle rm -rf/tmp/* rm -rf/tmp/ora* rm -rf/var/tmp ...

  2. CreateWindowEx详解

    语法: HWND CreateWindowEx( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, ...

  3. WM

    #define WM_NULL 0x0000 #define WM_CREATE 0x0001 #define WM_DESTROY 0x0002 #define WM_MOVE 0x0003 #de ...

  4. java_StringBuffer、StringBuilder

    StringBuffer和StringBuider是可变的字符串,使用方法 相同,StringBuffer是线程安全的,StringBuider是线程不安全的 public class StringT ...

  5. Java 调用存储过程 返回结果集

    这里使用Oracle数据库的thin连接. 下面是存储过程SQL 1 createorreplaceprocedure proc3(stid in student.stuid%type, stname ...

  6. [NOI2005]聪聪与可可

    题目大意:有小a和小b,其中一个人到处乱走,每次走一步:另一个人抄近路逼近,每次1-2步.求期望路程. 整解:跑1000遍最短路/bfs,求两两距离,然后找从x逼近y第一步去哪,最后期望dp收场. d ...

  7. <Linux> 下安装和卸载JDK

    安装 下载jdk https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 在local ...

  8. linux arping-通过发送ARP协议报文测试网络

    博主推荐:更多网络测试相关命令关注 网络测试  收藏linux命令大全 arping命令是用于发送arp请求到一个相邻主机的工具,arping使用arp数据包,通过ping命令检查设备上的硬件地址.能 ...

  9. 树莓派-3 启用root

    默认是user: pi,  password: raspberry 通过如下设置root密码并启用 pi@raspberrypi:~ $ sudo passwd root Enter new UNIX ...

  10. ruby 第五次作业 part 1(分类、排序)

    movies_controller.rb class MoviesController < ApplicationController def movie_params params.requi ...