多路复用I/O模型epoll() 模型 代码实现
epoll模型
int epoll_create(int maxevent) //创建一个epoll的句柄 然后maxevent表示监听的数目的大小
int epoll_ctl(int epollfd,int op,int fd,struct epoll_event *event) //epoll的事件注册函数
/*
epollfd 为epoll_create()的返回值
op 表示为相应的操作
fd 为套接字
*event 表示监听什么事件
*/
OP 有
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
int epoll_wait(int epollfd,struct epoll_event *event,int maxevents,int timeout);
/*
epollfd epoll_create的返回值
*event 从内核得到时间的集合
maxevents 告诉内核event多大 不能大于epoll_create()中的maxevent
timeout 表示等待的时间-1表示阻塞 0表示立即返回
*/
epoll_event结构体
- struct epoll_event {
- __uint32_t events; /* Epoll events */
- epoll_data_t data; /* User data variable */
- };
- typedef union epoll_data
- {
- void *ptr;
- int fd;
- uint32_t u32;
- uint64_t u64;
- } epoll_data_t;
其中epoll_event 结构体中的events参数的值是宏定义:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
data.h
- #ifndef DATA_H
- #define DATA_H
- #include <string.h>
- #include <stdio.h>
- #include <sys/epoll.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <assert.h>
- #include <sys/types.h>
- #define IP "127.0.0.1"
- #define PORT 4578
- #define maxn 1100
- #define MAXLINE 100
- #define BACKLOG 5
- #define EPOLLEVENTS 1120
- #define _EVENTS 100
- #endif
server.c
- #include "data.h"
- static void epoll_accept(int sockfd);
- static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
- static void submit_to_read(int epollfd,int conn,char *buf);
- static void submit_to_write(int epollfd,int conn,char *buf);
- static void submit_to_accept(int epollfd,int conn);
- static void change_event(int epollfd,int conn,int ser_event);
- static void change_delete(int epollfd,int conn,int ser_event);
- static void add_event(int epollfd,int sockfd,int ser_event);
- static int init()
- {
- int sockfd;
- struct sockaddr_in server_in;
- if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
- {
- fprintf(stderr,"socket fail,error %s",strerror(errno));
- return -;
- }
- bzero(&server_in,sizeof(server_in));
- server_in.sin_family = AF_INET;
- server_in.sin_port = htons(PORT);
- inet_pton(AF_INET,IP,&server_in.sin_addr);
- if(bind(sockfd,(struct sockaddr*)&server_in,sizeof(server_in)) == -)
- {
- fprintf(stderr,"bind fail,error %s",strerror(errno));
- return -;
- }
- listen(sockfd,BACKLOG);
- return sockfd;
- }
- static void epoll_accept(int sockfd)
- {
- int epollfd;
- char buf[maxn];
- memset(buf,,sizeof(buf));
- struct epoll_event events[_EVENTS];
- epollfd = epoll_create(EPOLLEVENTS);
- int ret;
- add_event(epollfd,sockfd,EPOLLIN);
- for(;;)
- {
- ret = epoll_wait(epollfd,events,_EVENTS,-);
- submit_to_check(epollfd,events,ret,sockfd,buf);
- }
- close(epollfd);
- }
- static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
- {
- int i;
- int fd;
- for(i=;i<num;i++)
- {
- fd = events[i].data.fd;
- if((fd == sockfd) && (events[i].events&EPOLLIN))
- {
- submit_to_accept(epollfd,sockfd);
- }
- else if(events[i].events & EPOLLIN)
- {
- submit_to_read(epollfd,fd,buf);
- }
- else if(events[i].events & EPOLLOUT)
- {
- submit_to_write(epollfd,fd,buf);
- }
- }
- }
- static void submit_to_read(int epollfd,int conn,char *buf)
- {
- int n;
- n = read(conn,buf,maxn);
- if(n == )
- {
- fprintf(stderr,"client close!\n");
- close(conn);
- change_delete(epollfd,conn,EPOLLIN);
- }
- else if(n == -)
- {
- fprintf(stderr,"read error\n");
- close(conn);
- change_delete(epollfd,conn,EPOLLIN);
- }
- else
- {
- fprintf(stderr,"read message is %s\n",buf);
- change_event(epollfd,conn,EPOLLOUT);
- }
- }
- static void submit_to_write(int epollfd,int conn,char *buf)
- {
- int n;
- n = write(conn,buf,strlen(buf));
- if(n == -)
- {
- printf("server closed!\n");
- close(conn);
- change_delete(epollfd,conn,EPOLLOUT);
- }
- else
- {
- change_event(epollfd,conn,EPOLLIN);
- }
- memset(buf,'\0',sizeof(buf));
- }
- static void submit_to_accept(int epollfd,int conn)
- {
- struct sockaddr_in server_in;
- bzero(&server_in,sizeof(server_in));
- socklen_t socklen;
- int afd;
- socklen = ;
- if((afd = accept(conn,(struct sockaddr*)&server_in,&socklen)) == -)
- {
- fprintf(stderr,"accept fail,error %s\n",strerror(errno));
- return;
- }
- else
- {
- printf("accept a new client:%s :%d\n",inet_ntoa(server_in.sin_addr),server_in.sin_port);
- add_event(epollfd,afd,EPOLLIN);
- }
- }
- static void change_event(int epollfd,int conn,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = conn;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_MOD,conn,&eventfd);
- }
- static void change_delete(int epollfd,int conn,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = conn;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_DEL,conn,&eventfd);
- }
- static void add_event(int epollfd,int sockfd,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = sockfd;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
- }
- int main()
- {
- int sockfd;
- sockfd = init();
- epoll_accept(sockfd);
- close(sockfd);
- return ;
- }
client.c
- #include "data.h"
- static void connect_server(int sockfd);
- static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
- static void submit_to_read(int epollfd,int fd,int sockfd,char *buf);
- static void submit_to_write(int epollfd,int fd,int sockfd,char *buf);
- static void change_event(int epollfd,int sockfd,int ser_event);
- static void change_delete(int epollfd,int sockfd,int ser_event);
- static void add_event(int epollfd,int sockfd,int ser_event);
- static int init()
- {
- struct sockaddr_in client_in;
- int sockfd;
- if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
- {
- fprintf(stderr,"socket fail,error %s\n",strerror(errno));
- return -;
- }
- bzero(&client_in,sizeof(client_in));
- client_in.sin_family = AF_INET;
- client_in.sin_port = htons(PORT);
- inet_pton(AF_INET,IP,&client_in.sin_addr);
- connect(sockfd,(struct sockaddr*)&client_in,sizeof(client_in)) ;
- return sockfd;
- }
- static void connect_server(int sockfd)
- {
- int epollfd;
- struct epoll_event events[_EVENTS];
- epollfd = epoll_create(EPOLLEVENTS);
- char buf[maxn];
- int conn;
- memset(buf,'\0',sizeof(buf));
- add_event(epollfd,STDIN_FILENO,EPOLLIN);
- for(;;)
- {
- fprintf(stderr,"Please input message!\n");
- conn = epoll_wait(epollfd,events,_EVENTS,-);
- submit_to_check(epollfd,events,conn,sockfd,buf);
- }
- close(epollfd);
- }
- static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
- {
- int i;
- int fd;
- for(i=;i<num;i++)
- {
- fd = events[i].data.fd;
- if(events[i].events & EPOLLIN)
- {
- submit_to_read(epollfd,fd,sockfd,buf);
- }
- else if(events[i].events & EPOLLOUT)
- {
- submit_to_write(epollfd,fd,sockfd,buf);
- }
- }
- }
- static void submit_to_read(int epollfd,int fd,int sockfd,char *buf)
- {
- memset(buf,'\0',sizeof(buf));
- int n;
- n = read(fd,buf,maxn);
- if(n == )
- {
- fprintf(stderr,"server close.\n");
- close(fd);
- }
- else if(n == -)
- {
- perror("read error:");
- close(fd);
- }
- else
- {
- if(fd == STDIN_FILENO)
- add_event(epollfd,sockfd,EPOLLOUT);
- else
- {
- change_delete(epollfd,sockfd,EPOLLIN);
- add_event(epollfd,STDOUT_FILENO,EPOLLOUT);
- }
- }
- }
- static void submit_to_write(int epollfd,int fd,int sockfd,char *buf)
- {
- int n;
- n = write(fd,buf,strlen(buf));
- if(n == -)
- {
- perror("write error:");
- close(fd);
- }
- else
- {
- if(fd == STDOUT_FILENO)
- {
- change_delete(epollfd,fd,EPOLLOUT);
- }
- else
- {
- change_event(epollfd,fd,EPOLLIN);
- }
- }
- memset(buf,,sizeof(buf));
- }
- static void change_event(int epollfd,int sockfd,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = sockfd;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_MOD,sockfd,&eventfd);
- }
- static void change_delete(int epollfd,int sockfd,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = sockfd;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_DEL,sockfd,&eventfd);
- }
- static void add_event(int epollfd,int sockfd,int ser_event)
- {
- struct epoll_event eventfd;
- eventfd.data.fd = sockfd;
- eventfd.events = ser_event;
- epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
- }
- int main()
- {
- int sockfd = init();
- connect_server(sockfd);
- close(sockfd);
- return ;
- }
多路复用I/O模型epoll() 模型 代码实现的更多相关文章
- nginx中的epoll模型
要了解epoll模型,就要一个一个知识点由浅至深地去探索. 1.IO复用技术 IO流请求操作系统内核,有串行处理和并行处理两种概念. 串行处理是前面一个操作处理地时候,后面的所有操作都需要等待.因此, ...
- 多路复用I/O模型poll() 模型 代码实现
多路复用I/O模型poll() 模型 代码实现 poll()机制和select()机制是相似的,都是对多个描述符进行轮询的方式. 不同的是poll()没有描述符数目的限制. 是通过struct pol ...
- Epoll模型详解
Linux 2.6内核中提高网络I/O性能的新方法-epoll I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数. 1.为什么select落后 首先,在Lin ...
- 【转】select和epoll模型的差异
http://www.cppblog.com/converse/archive/2008/10/12/63836.html epoll为什么这么快 epoll是多路复用IO(I/O Multiplex ...
- linux epoll模型
原文:http://yjtjh.blog.51cto.com/1060831/294119 Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数.Linux ...
- (OK) Linux epoll模型—socket epoll server client chat
http://www.cnblogs.com/venow/archive/2012/11/30/2790031.html http://blog.csdn.net/denkensk/article/d ...
- 基于EPOLL模型的局域网聊天室和Echo服务器
一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...
- 并发编程-epoll模型的探索与实践
前言 我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,sele ...
- go标准库I/O模型:epoll+多协程
本文为linux环境下的总结,其他操作系统本质差别不大.本地文件I/O和网络I/O逻辑类似. epoll+多线程的模型 epoll+多线程模型和epoll 单进程区别.优点 对比于redis这 ...
随机推荐
- BZOJ2795/2890/3647 [Poi2012]A Horrible Poem 【字符串hash】
题目链接 BZOJ2795 BZOJ2890 BZOJ3647 题解 三倍经验! 我们要快速求区间最小循环节 我们知道循环节有如下性质: ①当\(L\)为循环节长度,那么\(s[l...r - L] ...
- UVA.674 Coin Change (DP 完全背包)
UVA.674 Coin Change (DP) 题意分析 有5种硬币, 面值分别为1.5.10.25.50,现在给出金额,问可以用多少种方式组成该面值. 每种硬币的数量是无限的.典型完全背包. 状态 ...
- 51nod 1257 背包问题 V3(分数规划)
显然是分数规划...主要是不会求分数的形式,看了题解发现自己好傻逼QAQ 还是二分L值算出d[]降序选K个,顺便记录选择时候的p之和与w之和就可以输出分数形式了... #include<iost ...
- 解决webstrom 输入法光标不跟随问题
参考博客地址 https://blog.csdn.net/wang414300980/article/details/79537875 原因是jdk版本问题,下载jdk jbsdk8u152b1036 ...
- caffe中使用crop_size剪裁训练图片
layer { name: "data" type: "Data" top: "data" top: "label" i ...
- ACE自适配通信环境简介
转载于:http://www.cnblogs.com/TianFang/archive/2006/12/03/580795.html ACE自适配通信环境 (Adaptive Communicatio ...
- RotateAnimation 详解
RotateAnimation 详解 看看新闻网>看引擎>开源产品 其他构造器的旋转也可参考这副图. RotateAnimation旋转坐标系为以旋转点为坐标系(0,0)点.x轴为0度,顺 ...
- [技巧篇]03.关于MyBatis的简单批量处理
- maven工程pom.xml报Missing artifact net.sf.jasperreports:jasperreports:jar:6.2.0
有时maven工程的pom.xml报以下类型错误: Description Resource Path Location TypeMissing artifact net.sf.jasperrepor ...
- Android数据过滤器:Filter
类图: 通常可以将SearchView和ListView结合,实现数据的搜索和过滤. 1.监听SearchView,SearchView.setOnQueryTextListener(OnQueryT ...