相对于select来说,poll 也是在指定时间内论询一定数量的文件描述符,来测试其中是否有就绪的,不过,poll 提供了一个易用的方法,来实现 i/o 复用。

声明如下:

       #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 */
};

  fd 为文件描述符,events 告诉poll 监听fd 上哪些事件,它是一系列事件按位或。revents 由内核修改,来通知应用程序fd 上实际上发生了哪些事件。

nfds 为监听事件集合fds的大小

timeout 为poll的超时时间,单位毫秒。timeout 为-1时,poll永远阻塞,直到有事件发生。timeout为0时,poll立即返回。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h> #include <map>
#include <string> using namespace std; #define BUFSIZE 10
#define CLIENTSIZE 100 int createSocket()
{
struct sockaddr_in servaddr;
int listenfd = -1; if (-1 == (listenfd = socket(PF_INET, SOCK_STREAM, 0)))
{
fprintf(stderr, "socket: %d, %s\n", errno, strerror(errno));
exit(1);
} int reuseaddr = 1;
if (-1 == setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)))
{
fprintf(stderr, "setsockopt: %d, %s\n", errno, strerror(errno));
exit(1);
} memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = PF_INET;
servaddr.sin_port = htons(8008);
inet_pton(PF_INET, "0.0.0.0", &servaddr.sin_addr); if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)))
{
fprintf(stderr, "bind: %d, %s\n", errno, strerror(errno));
exit(1);
} if (-1 == listen(listenfd, 5))
{
fprintf(stderr, "listen: %d, %s\n", errno, strerror(errno));
exit(1);
} return listenfd;
} int setnoblock(int fd)
{
int oldopt = fcntl(fd, F_GETFL);
int newopt = oldopt | O_NONBLOCK;
fcntl(fd, F_SETFL, newopt);
return oldopt;
} int main()
{
struct pollfd fds[CLIENTSIZE];
int listenfd = createSocket(); map<int, string> mapdata; fds[0].fd = listenfd;
fds[0].events = POLLIN | POLLERR;
fds[0].revents = 0;
int conncount = 0; while (1)
{
int ret = poll(fds, conncount + 1, -1);
if (ret < 0)
{
fprintf(stderr, "poll: %d, %s\n", errno, strerror(errno));
exit(1);
} for (int i = 0; i < conncount + 1; i++)
{
// 客户端关闭,或者错误。错误的原因是由于客户端关闭导致的,这里一并处理
if ((fds[i].revents & POLLRDHUP) || (fds[i].revents & POLLERR))
{
int fd = fds[i].fd;
fds[i] = fds[conncount];
i--;
conncount--;
mapdata.erase(fd);
close(fd);
printf("delete connection: %d\n", fd);
}
// 新的连接
else if ((fds[i].fd == listenfd) && (fds[i].revents & POLLIN))
{
struct sockaddr_in client;
socklen_t lenaddr = sizeof(client);
int conn = -1; if (-1 == (conn = accept(listenfd, (struct sockaddr*)&client, &lenaddr)))
{
fprintf(stderr, "accept: %d, %s\n", errno, strerror(errno));
exit(1);
}
printf("get connection %d from %s:%d\n", conn, inet_ntoa(client.sin_addr), client.sin_port);
conncount++;
setnoblock(conn);
fds[conncount].fd = conn;
fds[conncount].events = POLLIN | POLLRDHUP | POLLERR;
fds[conncount].revents = 0;
}
// 有可读数据
else if (fds[i].revents & POLLIN)
{
char buf[BUFSIZE] = {0}; int lenrecv = recv(fds[i].fd, buf, BUFSIZE-1, 0);
if (lenrecv > 0)
{
mapdata[fds[i].fd] = buf;
fds[i].events &= (~POLLIN);
fds[i].events |= POLLOUT;
}
else if (lenrecv == 0)
{
printf("------- client %d exit (not print) --------\n", fds[i].fd);
}
else
{
fprintf(stderr, "recv: %d, %s\n", errno, strerror(errno));
exit(1);
}
}
// 可写数据
else if (fds[i].revents & POLLOUT)
{
if (send(fds[i].fd, mapdata[fds[i].fd].c_str(), mapdata[fds[i].fd].size(), 0) < 0)
{
if (ECONNRESET == errno)
{
continue;
}
fprintf(stderr, "send: %d, %s\n", errno, strerror(errno));
exit(1);
}
fds[i].events &= (~POLLOUT);
fds[i].events |= POLLIN;
}
}
}
}

  

linux poll用法的更多相关文章

  1. linux curl用法详解

    linux ‍‍curl用法详解 ‍‍curl的应用方式,一是可以直接通过命令行工具,另一种是利用libcurl库做上层的开发.本篇主要总结一下命令行工具的http相关的应用, 尤其是http下载方面 ...

  2. [转载]expect spawn、linux expect 用法小记

    原文地址:expect spawn.linux expect 用法小记作者:悟世 使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄.收藏.可是为什么要这么写 ...

  3. Linux poll机制

    1.用户空间调用(参考 poll(2) - Linux man page) int poll(struct pollfd *fds, nfds_t nfds, int timeout); it wai ...

  4. [转帖]linux lsof 用法简介

    linux lsof 用法简介 https://www.cnblogs.com/saneri/p/5333333.html 1.简介: lsof(list open files)是一个列出当前系统打开 ...

  5. linux poll 和 select

    使用非阻塞 I/O 的应用程序常常使用 poll, select, 和 epoll 系统调用. poll, select 和 epoll 本质上有相同的功能: 每个允许一个进程来决定它是否可读或者写一 ...

  6. Linux find 用法示例

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  7. linux poll 学习

    一.poll介绍 函数原型: #include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); struc ...

  8. linux gksu用法

    apt-get install gksu gksu是linux下图形化的su/sudo工具 sudo 用来执行命令行(CLI)程序 gksu 用来执行图形的(GUI)程序 GUI = Graphica ...

  9. linux exec用法总结

    Linux中exec的用法总结 先总结一个表: exec命令 作用 exec ls 在shell中执行ls,ls结果显示结束后不返回原来的的目录中,而是/(根目录) exec <file 将fi ...

随机推荐

  1. Cookie概述

    一.什么叫Cookie? Cookie翻译成中文是小甜点,小饼干,在Http中它表示服务器送给客户端浏览器的小甜点.其实Cookie就是一个键和一个值构成,随着服务器端的响应发送给客户端浏览器,然后客 ...

  2. qingdao

    1001 #include <bits/stdc++.h> using namespace std; vector<long long> v; long long pow2(l ...

  3. 【Angular JS】网站使用社会化评论插件,以及过程中碰到的坑

    目前正在开发自己的网站,技术上使用Angular JS + Express JS + Mongo DB.由于网站会有文章发布,因此需要有评论功能.评论功能也可以自己开发,但由于现在社会化评论插件很多, ...

  4. 【转】【MATLAB】模拟和数字低通滤波器的MATLAB实现

    原文地址:http://blog.sina.com.cn/s/blog_79ecf6980100vcrf.html 低通滤波器参数:Fs=8000,fp=2500,fs=3500,Rp=1dB,As= ...

  5. Java 空对象设计模式(Null Object Pattern) 讲解

    转自:http://www.cnblogs.com/haodawang/articles/5962531.html 有时候我们的代码中为避免 NullPointerException 会出现很多的对N ...

  6. selenium鼠标拖动

    var builder = new Actions(_driver); builder.MoveToElement(_driver.GetElementByCssSelector("#com ...

  7. $("#Upfile").MultiFile();

    Jquery的multifile 1.多文件上传: 2.如上几个验证不重复,和限制上传数量的验证显示的是英文,改成中文文本时,如果不用国标解码,到时候提示框会出现乱码现象.所以一般需要中文显示的时候, ...

  8. vos设置可呼出手机或固话

    问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关——补充设置——落地前缀——落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201——1表示让520号段只能拨 ...

  9. 在android开发中如何使用JavaMail程序

    javaMail,是提供给开发者处理电子邮件相关的编程接口.它是Sun发布的用来处理email的API.它可以方便地执行一些常用的邮件传输.我们可以基于JavaMail开发出类似于Microsoft  ...

  10. 如何在markdown中实现缩进,空格,制表符

    参考 https://stackoverflow.com/questions/6046263/how-to-indent-a-few-lines-in-markdown-markup Markdown ...