select、poll、epoll程序实例
三个函数的基本用法如下:
select
创建
fd_set rset , allset;
FD_ZERO(&allset);
FD_SET(listenfd, &allset);
监听
/*只select出用于读的描述字,阻塞无timeout*/
nready = select(maxfd+1 , &rset , NULL , NULL , NULL);
获取
if(FD_ISSET(listenfd,&rset))
poll:
创建
struct pollfd client[OPEN_MAX];
client[0].fd = listenfd;
client[0].events = POLLRDNORM;
for(i=1;i<OPEN_MAX;i++)
{
client[i].fd = -1;
}
maxi = 0;
监听
nready = poll(client,maxi+1,INFTIM);
获取
sockfd = client[i].fd;
if(client[i].revents & (POLLRDNORM|POLLERR))
epoll:
创建
int epfd;
struct epoll_event ev, events[20];
epfd = epoll_create(256);
ev.data.fd=listenfd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
监听
nfds=epoll_wait(epfd,events,20,500);
获取
if (events[i].events & EPOLLIN)
IO复用,说得粗鄙一点,就是不用开多线程也能发送和接收消息。不多说,看代码:(select和poll是别人写的。引用一下,别见怪。)
select:
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h> const static int MAXLINE = ;
const static int SERV_PORT = ; int main()
{
int i , maxi , maxfd, listenfd , connfd , sockfd ;
/*nready 描述字的数量*/
int nready ,client[FD_SETSIZE];
int n ;
/*创建描述字集合,由于select函数会把未有事件发生的描述字清零,所以我们设置两个集合*/
fd_set rset , allset;
char buf[MAXLINE];
socklen_t clilen;
struct sockaddr_in cliaddr , servaddr;
/*创建socket*/
listenfd = socket(AF_INET , SOCK_STREAM , );
/*定义sockaddr_in*/
memset(&servaddr , ,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listenfd, (struct sockaddr *) & servaddr , sizeof(servaddr));
listen(listenfd , );
/*listenfd 是第一个描述字*/
/*最大的描述字,用于select函数的第一个参数*/
maxfd = listenfd;
/*client的数量,用于轮询*/
maxi = -;
/*init*/
for(i= ;i<FD_SETSIZE ; i++)
client[i] = -;
FD_ZERO(&allset);
FD_SET(listenfd, &allset); for (;;)
{
rset = allset;
/*只select出用于读的描述字,阻塞无timeout*/
nready = select(maxfd+ , &rset , NULL , NULL , NULL);
if(FD_ISSET(listenfd,&rset))
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd , (struct sockaddr *) & cliaddr , &clilen);
/*寻找第一个能放置新的描述字的位置*/
for (i=;i<FD_SETSIZE;i++)
{
if(client[i]<)
{
client[i] = connfd;
break;
}
}
/*找不到,说明client已经满了*/
if(i==FD_SETSIZE)
{
printf("Too many clients , over stack .\n");
return -;
}
FD_SET(connfd,&allset);//设置fd
/*更新相关参数*/
if(connfd > maxfd) maxfd = connfd;
if(i>maxi) maxi = i;
if(nready<=) continue;
else nready --;
} for(i= ; i<=maxi ; i++)
{
if (client[i]<) continue;
sockfd = client[i];
if(FD_ISSET(sockfd,&rset))
{
n = read(sockfd , buf , MAXLINE);
if (n==)
{
/*当对方关闭的时候,server关闭描述字,并将set的sockfd清空*/
close(sockfd);
FD_CLR(sockfd,&allset);
client[i] = -;
}
else
{
buf[n]='\0';
printf("Socket %d said : %s\n",sockfd,buf);
write(sockfd,buf,n); //Write back to client
}
nready --;
if(nready<=) break;
}
} }
return ;
}
poll:
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h> /*环境为ubuntu10.04自带c环境,无法自动引入下列宏,所以自己写在前面了*/
#define INFTIM -1
#define POLLRDNORM 0x040 /* Normal data may be read. */
#define POLLRDBAND 0x080 /* Priority data may be read. */
#define POLLWRNORM 0x100 /* Writing now will not block. */
#define POLLWRBAND 0x200 /* Priority data may be written. */ #define MAXLINE 1024
#define OPEN_MAX 16 //一些系统会定义这些宏
#define SERV_PORT 10001 int main()
{
int i , maxi ,listenfd , connfd , sockfd ;
int nready;
int n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPEN_MAX]; struct sockaddr_in cliaddr , servaddr;
listenfd = socket(AF_INET , SOCK_STREAM , );
memset(&servaddr,,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr));
listen(listenfd,);
client[].fd = listenfd;
client[].events = POLLRDNORM;
for(i=;i<OPEN_MAX;i++)
{
client[i].fd = -;
}
maxi = ; for(;;)
{
nready = poll(client,maxi+,INFTIM);
if (client[].revents & POLLRDNORM)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd , (struct sockaddr *)&cliaddr, &clilen);
for(i=;i<OPEN_MAX;i++)
{
if(client[i].fd<)
{
client[i].fd = connfd;
client[i].events = POLLRDNORM;
break;
}
}
if(i==OPEN_MAX)
{
printf("too many clients! \n");
}
if(i>maxi) maxi = i;
nready--;
if(nready<=) continue;
} for(i=;i<=maxi;i++)
{
if(client[i].fd<) continue;
sockfd = client[i].fd;
if(client[i].revents & (POLLRDNORM|POLLERR))
{
n = read(client[i].fd,buf,MAXLINE);
if(n<=)
{
close(client[i].fd);
client[i].fd = -;
}
else
{
buf[n]='\0';
printf("Socket %d said : %s\n",sockfd,buf);
write(sockfd,buf,n); //Write back to client
}
nready--;
if(nready<=) break; //no more readable descriptors
}
}
}
return ;
}
epoll:
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/resource.h> #define MAXLINE 1024
#define OPEN_MAX 16 //一些系统会定义这些宏
#define SERV_PORT 10001 int main()
{
int i , maxi ,listenfd , connfd , sockfd ,epfd, nfds;
int n;
char buf[MAXLINE];
struct epoll_event ev, events[];
socklen_t clilen;
struct pollfd client[OPEN_MAX]; struct sockaddr_in cliaddr , servaddr;
listenfd = socket(AF_INET , SOCK_STREAM , );
memset(&servaddr,,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(listenfd , (struct sockaddr *) & servaddr, sizeof(servaddr));
listen(listenfd,); epfd = epoll_create();
ev.data.fd=listenfd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); for(;;)
{
nfds=epoll_wait(epfd,events,,);
for(i=; i<nfds; i++)
{
if (listenfd == events[i].data.fd)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd , (struct sockaddr *)&cliaddr, &clilen);
if(connfd < )
{
perror("connfd < 0");
exit();
}
ev.data.fd=connfd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
}
else if (events[i].events & EPOLLIN)
{
if ( (sockfd = events[i].data.fd) < )
continue;
n = recv(sockfd,buf,MAXLINE,);
if (n <= )
{
close(sockfd);
events[i].data.fd = -;
}
else
{
buf[n]='\0';
printf("Socket %d said : %s\n",sockfd,buf);
ev.data.fd=sockfd;
ev.events=EPOLLOUT|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,connfd,&ev);
}
}
else if( events[i].events&EPOLLOUT )
{
sockfd = events[i].data.fd;
send(sockfd, "Hello!", , ); ev.data.fd=sockfd;
ev.events=EPOLLIN|EPOLLET;
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}
else
{
printf("This is not avaible!");
}
}
}
close(epfd);
return ;
}
select、poll、epoll程序实例的更多相关文章
- Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...
- 多进程、协程、事件驱动及select poll epoll
目录 -多线程使用场景 -多进程 --简单的一个多进程例子 --进程间数据的交互实现方法 ---通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享 ---Queues ---P ...
- Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO
本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO 1. 多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...
- select poll epoll三者之间的比较
一.概述 说到Linux下的IO复用,系统提供了三个系统调用,分别是select poll epoll.那么这三者之间有什么不同呢,什么时候使用三个之间的其中一个呢? 下面,我将从系统调用原型来分析其 ...
- select, poll, epoll的实现分析
select, poll, epoll都是Linux上的IO多路复用机制.知其然知其所以然,为了更好地理解其底层实现,这几天我阅读了这三个系统调用的源码. 以下源代码摘自Linux4.4.0内核. 预 ...
- 转--select/poll/epoll到底是什么一回事
面试题:说说select/poll/epoll的区别. 这是面试后台开发时的高频面试题,属于网络编程和IO那一块的知识.Android里面的Handler消息处理机制的底层实现就用到了epoll. 为 ...
- python 套接字之select poll epoll
python下的select模块使用 以及epoll与select.poll的区别 先说epoll与select.poll的区别(总结) select, poll, epoll 都是I/O多路复用的具 ...
- Linux I/O复用中select poll epoll模型的介绍及其优缺点的比較
关于I/O多路复用: I/O多路复用(又被称为"事件驱动"),首先要理解的是.操作系统为你提供了一个功能.当你的某个socket可读或者可写的时候.它能够给你一个通知.这样当配合非 ...
- Select/Poll/Epoll异步IO
IO多路复用 同步io和异步io,阻塞io和非阻塞io分别是什么,有什么样的区别? io模式 对于一次io 访问(以read为例),数据会先拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷 ...
- Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程
1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...
随机推荐
- python+Eclipse+pydev环境搭建(转)
编辑器:Python 自带的 IDLE 简单快捷, 学习Python或者编写小型软件的时候.非常有用. 编辑器: Eclipse + pydev插件 1. Eclipse是写JAVA的IDE, 这样就 ...
- iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合
1.地图坐标转换那些事 (1)投影坐标系与地理坐标系 地理坐标系使用三维球面来定义地球上的位置,单位即经纬度.但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据.通过投影的方式可以 ...
- iOS 通过二进制判断图片类型
+ (NSString *)typeForImageData:(NSData *)data { uint8_t c; [data getBytes:&c length:1]; switch ( ...
- eclipse执行单元测试报CreateProcess error=87的解决方法
原因是classpath的路径过长导致,在网上看了很多文章,发现解决方法有2种: 1.更改项目路径 或者 maven本地库的路径,减少classpath的深度. 2.由于这是eclipse自身的bug ...
- Windows 7 与 Vmware Ubuntu 15.10_64 共享文件夹
设置共享文件夹 安装/更新最新的vmware-tools 安装 在ubuntu 内部会打开DVD ,里面的压缩包中包含vmware-toole. 先解压 ...
- OOD沉思录 --- 类和对象的关系 --- 包含关系3
4.7 类包含的对象数目不应当超过开发者短期记忆数量,这个数目通常应该是6左右 4.8 让系统在窄而深的包含体系中垂直分布 假设有如下两份菜单: 正餐 --->甜瓜 --->牛排 ---& ...
- nginx设置反向代理后,页面上的js css文件无法加载
问题现象: nginx配置反向代理后,网页可以正常访问,但是页面上的js css文件无法加载,页面样式乱了. (1)nginx配置如下: (2)域名访问:js css文件无法加载: (3)IP访问:j ...
- 在SQL2008R2查询分析器出错(在执行批处理时出现错误。错误消息为: 目录名称无效。)
在用SQL2008R2查询分析器时 SELECT * FROM 表名; 出错: 在执行批处理时出现错误.错误消息为: 目录名称无效. 原因: 在打开查询分析器时,用360软件清空了临时文件(只是偶尔1 ...
- DNS报文格式
原文链接地址:http://blog.chinaunix.net/uid-24875436-id-3088461.html DNS报文格式(借个图贴过来): 说明一下:并不是所有DNS报文都有 ...
- jiulianhuan 快速幂--矩阵快速幂
题目信息: 1471: Jiulianhuan 时间限制: 1 Sec 内存限制: 128 MB 提交: 95 解决: 22 题目描述 For each data set in the input ...