linux 下 poll 编程

  poll 与 select 很类似,都是对描述符进行遍历,查看是否有描述符就绪。如果有就返回就绪文件描述符的个数将。poll 函数如下:

  #include <poll.h>

  int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)

  第一个参数指向结构数组第一个元素的指针,每个数组都是一个 pollfd 结构iouyonghu制定额是某个给定描述符的条件。

  struct pollfd

  {

    int fd;

    short events;//关心 fd 上发生的事件

    short revents;//fd 实际上上发生的事件

  }

  第二个参数 nfds 制定数组中元素个数。第三个参数指定 poll 函数返回前等待多长时间。 INFTIM 表示永远等待, 0 代表立即返回, > 0 等待指定数目的秒数。

  poll 编程实例,这是 TCP 连接服务器端代码:

  1 #include <sys/socket.h>
  2 #include <netinet/in.h>
  3 #include <stdio.h>
  4 #include <error.h>
  5 #include <errno.h>
  6 #include <unistd.h>
  7 #include <string.h>
  8 #include <stdlib.h>
  9 #include <sys/wait.h>
 10 #include <limits.h>
 11 #include <poll.h>
 12 #include <sys/stropts.h>
 13 #include <signal.h>
 14 #define MAXLINE 5
 15 #define OPEN_MAX 1024
 16 #define SA struct sockaddr
 17
 18
 19 int main()
 20 {
 21     int listenfd, connfd, sockfd, i, maxi;
 22     int nready;
 23     socklen_t clilen;
 24     ssize_t n;
 25     char buf[MAXLINE];
 26     struct pollfd client[OPEN_MAX];
 27     struct sockaddr_in servaddr, cliaddr;
 28     //创建监听套接字
 29     if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 30     {
 31         printf("socket() error!");
 32         exit(0);
 33     }
 34     //先要对协议地址进行清零
 35     bzero(&servaddr,sizeof(servaddr));
 36     //设置为 IPv4 or IPv6
 37     servaddr.sin_family = AF_INET;
 38     //绑定本地端口号
 39     servaddr.sin_port    = htons(9805);
 40     //任何一个 IP 地址,让内核自行选择
 41     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 42     //绑定套接口到本地协议地址
 43     if(bind(listenfd, (SA *) &servaddr,sizeof(servaddr)) < 0)
 44     {
 45         printf("bind() error!");
 46         exit(0);
 47     }
 48     //服务器开始监听
 49     if(listen(listenfd,5) < 0)
 50     {
 51         printf("listen() error!");
 52         exit(0);
 53     }
 54     client[0].fd = listenfd;
 55     client[0].events = POLLRDNORM;//关心监听套机字的读事件
 56     for(i = 1; i < OPEN_MAX; ++i)
 57     {
 58         client[i].fd = -1;
 59     }
 60     maxi = 0;
 61     for(;;)
 62     {
 63         nready = poll(client, maxi + 1, -1);
 64         if(client[0].revents & POLLRDNORM)
 65         {
 66             clilen = sizeof(cliaddr);
 67             //accept 的后面两个参数都是值-结果参数,他们的保留的远程连接电脑的信息,如果不管新远程连接电脑的信息,可以将这两个参数设置为 NULL
 68             connfd = accept(listenfd, (SA *) &cliaddr, &clilen);
 69             if(connfd < 0)
 70             {
 71                 continue;
 72             }
 73             for(i = 1; i < OPEN_MAX; ++i)
 74             {
 75                 if(client[i].fd < 0)
 76                     client[i].fd = connfd;
 77                 break;
 78             }
 79             if(i == OPEN_MAX)
 80             {
 81                 printf("too many clients");
 82                 exit(0);
 83             }
 84             client[i].events = POLLRDNORM;
 85             if(i > maxi)
 86             {
 87                 maxi = i;
 88             }
 89             if(--nready <=0 )
 90                 continue;
 91         }
 92         for(i = 1; i < OPEN_MAX; ++i)
 93         {
 94             if((sockfd = client[i].fd) < 0)
 95             {
 96                 continue;
 97             }
 98             if(client[i].revents & POLLRDNORM | POLLERR)
 99             {
100                 if((n = read(sockfd, buf, MAXLINE)) < 0)
101                 {
102                     if(errno == ECONNRESET)
103                     {
104                         close(sockfd);
105                         client[i].fd = -1;
106                     }
107                     else
108                     {
109                         printf("read error!\n");
110                     }
111                 }
112                 else if(n == 0)
113                 {
114                     close(sockfd);
115                     client[i].fd = -1;
116                 }
117                 else
118                 {
119                     write(sockfd, buf,  n);
120                 }
121                 if(--nready <= 0)
122                     break;
123             }
124         }
125     }
126 }

  配合 linux 下 select 编程 就是一个完整的客户端/服务器端代码了,运行结果截图如下:

  客户端:

  

  服务器端:

    

    

时间: 2024-08-19 03:40:25

linux 下 poll 编程的相关文章

根据《linux兵书》目录 在kali上操作 第8章 Linux下的编程

第8章  浑水摸鱼:Linux下的编程 175 8.1  Linux下常用的开发工具 176 8.1.1  GCC 176 8.1.2  CVS 176 8.1.3  Perl 176 8.1.4  Linux上的Delphi--Kylix 177 8.2  Linux下的Vi文本编辑器 177 8.2.1  Vi编辑器介绍 178 8.2.2  启动Vi编辑器 179 8.2.3  显示Vi中的行号 180 8.2.4  光标移动操作 181 8.2.5  屏幕命令 182 8.2.6  文本

Linux下Socket编程

http://blog.chinaunix.net/uid-20733992-id-3450058.html 原文地址:Linux下Socket编程 作者:yulianliu1218 Linux下Socket编程 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. Socket接口设计者最先是将接口放在Unix操作系统里面

Linux下Socket编程的端口问题( Bind error: Address already in use )

Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误: Bind error: Address already in use 虽然用Ctrl+C强制结束了进程,但错误依然存在,用netstat -an |grep 5120和ps aux |grep 5120都还能看到刚才用Ctrl+C“强制结束”了的进程,端口还是使用中,只好每次用kill结束进程,

Linux下Shell编程

Linux的shell编程 1.什么是shell? 当一个用户登录Linux系统之后,系统初始化程序init就为每一个用户运行一个称为shell(外壳)的程序. shell就是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动.挂起.停止甚至是编写一些程序.一般的Linux系统都将bash作为默认的shell. 2.几种流行的shell 目前流行的shell有ash.bash.ksh.csh.zsh等,可以用下面的命令来查看she

Linux下shell编程实例

1. 判断一文件是不是块或字符设备文件,如果是将其拷贝到 /dev 目录下 read -p "input a file:" filename if [ -b $filename -o -c $filename ] then cp $filename /dev/ fi 2.编写一个脚本,进行简单的减法运算,要求提示输入变量 #!/bin/bash read -p "input a number:" num1 read -p "input another nu

linux下Bash编程组合测试及编写脚本(五)

linux下Bash编程组合测试及编写综合脚本(五) 1.Bash编程组合测试条件 -a: 与关系 -o: 或关系 !: 非关系 表示方法1:[ $# -gt 100 -a $# -le 500 ] 表示方法2:[ $# -gt 100 ] && [ $# -le 500 ] 2.编写一个任意添加与删除用户的脚本,要求如下: 2.1:如果脚本选项是--add:,将添加用户; 如果选项是--del,将删除用户,如果是--help显示帮助信息 2.2:脚本选项后面的参数可任意指定多个用户并且用

linux下多线程编程

最近研究mysql源码,各种锁,各种互斥,好在我去年认真学了<unix环境高级编程>, 虽然已经忘得差不多了,但是学过始终是学过,拿起来也快.写这篇文章的目的就是总结linux 下多线程编程,作为日后的参考资料. 本文将介绍linux系统下多线程编程中,线程同步的各种方法.包括: 互斥量(mutex) 读写锁 条件变量 信号量 文件互斥 在介绍不同的线程同步的方法之前,先简单的介绍一下进程和线程的概念, 它们的优缺点,线程相关的API,读者——写者问题和哲学家就餐问题. 基础知识 1. 进程和

Linux下socket编程,附带tcp例子

1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问

Linux下C编程入门

1.首先,以Ubuntu 64-bit操作系统下为例 图中的sudo su表示的是快速进入到root管理员下.这里的密码默认的是安装后的Ubunto操作系统中自定义的用户名的密码,此处以用户toto,密码:123456为例 2.在/demo目录下创建以下三个文件(看截图): 注意:其中add.c的内容如下(通过vi编辑器编辑add.c): 其中的add.h(用于声明同级目录下的add.c文件中编写的函数).截图如下: 3.关于自定义add.h函数的引用,在main.c中的写法如下: 4.编译ad