三个函数的基本用法如下:

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程序实例的更多相关文章

  1. Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)

    一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...

  2. 多进程、协程、事件驱动及select poll epoll

    目录 -多线程使用场景 -多进程 --简单的一个多进程例子 --进程间数据的交互实现方法 ---通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享 ---Queues ---P ...

  3. Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO

    本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO   1.  多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...

  4. select poll epoll三者之间的比较

    一.概述 说到Linux下的IO复用,系统提供了三个系统调用,分别是select poll epoll.那么这三者之间有什么不同呢,什么时候使用三个之间的其中一个呢? 下面,我将从系统调用原型来分析其 ...

  5. select, poll, epoll的实现分析

    select, poll, epoll都是Linux上的IO多路复用机制.知其然知其所以然,为了更好地理解其底层实现,这几天我阅读了这三个系统调用的源码. 以下源代码摘自Linux4.4.0内核. 预 ...

  6. 转--select/poll/epoll到底是什么一回事

    面试题:说说select/poll/epoll的区别. 这是面试后台开发时的高频面试题,属于网络编程和IO那一块的知识.Android里面的Handler消息处理机制的底层实现就用到了epoll. 为 ...

  7. python 套接字之select poll epoll

    python下的select模块使用 以及epoll与select.poll的区别 先说epoll与select.poll的区别(总结) select, poll, epoll 都是I/O多路复用的具 ...

  8. Linux I/O复用中select poll epoll模型的介绍及其优缺点的比較

    关于I/O多路复用: I/O多路复用(又被称为"事件驱动"),首先要理解的是.操作系统为你提供了一个功能.当你的某个socket可读或者可写的时候.它能够给你一个通知.这样当配合非 ...

  9. Select/Poll/Epoll异步IO

    IO多路复用 同步io和异步io,阻塞io和非阻塞io分别是什么,有什么样的区别? io模式 对于一次io 访问(以read为例),数据会先拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷 ...

  10. Python异步非阻塞IO多路复用Select/Poll/Epoll使用,线程,进程,协程

    1.使用select模拟socketserver伪并发处理客户端请求,代码如下: import socket import select sk = socket.socket() sk.bind((' ...

随机推荐

  1. 【读书笔记】iOS-写代码注意事项

    一,我是尽早和经常编译的强烈支持者.通常,在写完每个方法或有点难度的代码后,都要尝试进行构建.这是一个好习惯,因为如果在上次成功编译以来添加的代码量很小,那么可以非常容易地缩小编译错误范围.这个方法还 ...

  2. iOS开发融云即时通讯集成详细步骤

    1.融云即时通讯iOS SDK下载地址   http://rongcloud.cn/downloads  选择iOS   SDK下载 2.进行应用开发之前,需要先在融云开发者平台创建应用,如果您已经注 ...

  3. iOS之 开发中用得到的开源github

    github:无限图片轮播 https://github.com/dymx101/DYMRollingBanner 2.灌水动画 https://github.com/dsxNiubility/SXW ...

  4. Cent OS服务器配置(JDK+Tomcat+MySQL)

    本文摘自:Cent OS服务器配置(JDK+Tomcat+MySQL) 学习tar解压 解压 tar 文件 tar -zxvf apache-tomcat-6.0.35.tar.gz tomcat   ...

  5. 关于git

    一.Git基础教程  01.[入门练习]廖雪峰 git教程网:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8 ...

  6. Effective Java 77 For instance control, prefer enum types to readResolve

    The readResolve feature allows you to substitute another instance for the one created by readObject ...

  7. php的amqp扩展set导致内存溢出

    最近做的一个项目中需要用到rabbitmq,按照自己的之前的一篇文章http://www.cnblogs.com/mingaixin/archive/2012/10/28/2743807.html进行 ...

  8. Java中的静态方法和单例模式比较

    区别 单例模式方法 静态方法 实例 创建实例 无 运行 类的实例的方法 类的方法 也可以通过实例化,在通过类的实例来运行 是否可以被重写 可以 可以(子类的该方法也必须是静态方法) 调用其他静态方法 ...

  9. sublime学习

    1:goto anything 特性 快捷键  ctrl + P    @  : # 使用 2:多行游标功能 快捷键 ctrl + D     ctrl + K 跳过选择 alt + F3 多选 产生 ...

  10. B+树的特点

    1.B+树是应文件系统产生的B树的变种.它依然是一颗多路查找树,与B树相比它的不同体现在: (1).如果非叶子节点包含n个关键码,则这个节点有n个子树. (2).非叶子节点仅包含关键码信息,叶子节点包 ...