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结构体

  1. struct epoll_event {
  2. __uint32_t events; /* Epoll events */
  3. epoll_data_t data; /* User data variable */
  4. };
  1. typedef union epoll_data
  2. {
  3. void *ptr;
  4. int fd;
  5. uint32_t u32;
  6. uint64_t u64;
  7. } epoll_data_t;

其中epoll_event 结构体中的events参数的值是宏定义:

EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

data.h

  1. #ifndef DATA_H
  2. #define DATA_H
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <sys/epoll.h>
  6. #include <sys/stat.h>
  7. #include <stdlib.h>
  8. #include <errno.h>
  9. #include <netinet/in.h>
  10. #include <sys/socket.h>
  11. #include <unistd.h>
  12. #include <arpa/inet.h>
  13. #include <assert.h>
  14. #include <sys/types.h>
  15.  
  16. #define IP "127.0.0.1"
  17. #define PORT 4578
  18. #define maxn 1100
  19. #define MAXLINE 100
  20. #define BACKLOG 5
  21. #define EPOLLEVENTS 1120
  22. #define _EVENTS 100
  23. #endif

server.c

  1. #include "data.h"
  2. static void epoll_accept(int sockfd);
  3. static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
  4. static void submit_to_read(int epollfd,int conn,char *buf);
  5. static void submit_to_write(int epollfd,int conn,char *buf);
  6. static void submit_to_accept(int epollfd,int conn);
  7. static void change_event(int epollfd,int conn,int ser_event);
  8. static void change_delete(int epollfd,int conn,int ser_event);
  9. static void add_event(int epollfd,int sockfd,int ser_event);
  10.  
  11. static int init()
  12. {
  13. int sockfd;
  14. struct sockaddr_in server_in;
  15. if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
  16. {
  17. fprintf(stderr,"socket fail,error %s",strerror(errno));
  18. return -;
  19. }
  20. bzero(&server_in,sizeof(server_in));
  21. server_in.sin_family = AF_INET;
  22. server_in.sin_port = htons(PORT);
  23. inet_pton(AF_INET,IP,&server_in.sin_addr);
  24. if(bind(sockfd,(struct sockaddr*)&server_in,sizeof(server_in)) == -)
  25. {
  26. fprintf(stderr,"bind fail,error %s",strerror(errno));
  27. return -;
  28. }
  29. listen(sockfd,BACKLOG);
  30. return sockfd;
  31. }
  32.  
  33. static void epoll_accept(int sockfd)
  34. {
  35. int epollfd;
  36. char buf[maxn];
  37. memset(buf,,sizeof(buf));
  38. struct epoll_event events[_EVENTS];
  39. epollfd = epoll_create(EPOLLEVENTS);
  40. int ret;
  41. add_event(epollfd,sockfd,EPOLLIN);
  42. for(;;)
  43. {
  44. ret = epoll_wait(epollfd,events,_EVENTS,-);
  45. submit_to_check(epollfd,events,ret,sockfd,buf);
  46. }
  47. close(epollfd);
  48. }
  49. static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
  50. {
  51. int i;
  52. int fd;
  53. for(i=;i<num;i++)
  54. {
  55. fd = events[i].data.fd;
  56. if((fd == sockfd) && (events[i].events&EPOLLIN))
  57. {
  58. submit_to_accept(epollfd,sockfd);
  59. }
  60. else if(events[i].events & EPOLLIN)
  61. {
  62. submit_to_read(epollfd,fd,buf);
  63. }
  64. else if(events[i].events & EPOLLOUT)
  65. {
  66. submit_to_write(epollfd,fd,buf);
  67. }
  68. }
  69. }
  70. static void submit_to_read(int epollfd,int conn,char *buf)
  71. {
  72. int n;
  73. n = read(conn,buf,maxn);
  74. if(n == )
  75. {
  76. fprintf(stderr,"client close!\n");
  77. close(conn);
  78. change_delete(epollfd,conn,EPOLLIN);
  79. }
  80. else if(n == -)
  81. {
  82. fprintf(stderr,"read error\n");
  83. close(conn);
  84. change_delete(epollfd,conn,EPOLLIN);
  85. }
  86. else
  87. {
  88. fprintf(stderr,"read message is %s\n",buf);
  89. change_event(epollfd,conn,EPOLLOUT);
  90. }
  91. }
  92. static void submit_to_write(int epollfd,int conn,char *buf)
  93. {
  94. int n;
  95. n = write(conn,buf,strlen(buf));
  96. if(n == -)
  97. {
  98. printf("server closed!\n");
  99. close(conn);
  100. change_delete(epollfd,conn,EPOLLOUT);
  101. }
  102. else
  103. {
  104. change_event(epollfd,conn,EPOLLIN);
  105. }
  106. memset(buf,'\0',sizeof(buf));
  107. }
  108. static void submit_to_accept(int epollfd,int conn)
  109. {
  110. struct sockaddr_in server_in;
  111. bzero(&server_in,sizeof(server_in));
  112. socklen_t socklen;
  113. int afd;
  114. socklen = ;
  115. if((afd = accept(conn,(struct sockaddr*)&server_in,&socklen)) == -)
  116. {
  117. fprintf(stderr,"accept fail,error %s\n",strerror(errno));
  118. return;
  119. }
  120. else
  121. {
  122. printf("accept a new client:%s :%d\n",inet_ntoa(server_in.sin_addr),server_in.sin_port);
  123. add_event(epollfd,afd,EPOLLIN);
  124. }
  125. }
  126. static void change_event(int epollfd,int conn,int ser_event)
  127. {
  128. struct epoll_event eventfd;
  129. eventfd.data.fd = conn;
  130. eventfd.events = ser_event;
  131. epoll_ctl(epollfd,EPOLL_CTL_MOD,conn,&eventfd);
  132. }
  133. static void change_delete(int epollfd,int conn,int ser_event)
  134. {
  135. struct epoll_event eventfd;
  136. eventfd.data.fd = conn;
  137. eventfd.events = ser_event;
  138. epoll_ctl(epollfd,EPOLL_CTL_DEL,conn,&eventfd);
  139. }
  140. static void add_event(int epollfd,int sockfd,int ser_event)
  141. {
  142. struct epoll_event eventfd;
  143. eventfd.data.fd = sockfd;
  144. eventfd.events = ser_event;
  145. epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
  146. }
  147.  
  148. int main()
  149. {
  150.  
  151. int sockfd;
  152. sockfd = init();
  153. epoll_accept(sockfd);
  154. close(sockfd);
  155. return ;
  156. }

client.c

  1. #include "data.h"
  2.  
  3. static void connect_server(int sockfd);
  4. static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf);
  5. static void submit_to_read(int epollfd,int fd,int sockfd,char *buf);
  6. static void submit_to_write(int epollfd,int fd,int sockfd,char *buf);
  7. static void change_event(int epollfd,int sockfd,int ser_event);
  8. static void change_delete(int epollfd,int sockfd,int ser_event);
  9. static void add_event(int epollfd,int sockfd,int ser_event);
  10.  
  11. static int init()
  12. {
  13. struct sockaddr_in client_in;
  14. int sockfd;
  15. if((sockfd = socket(AF_INET,SOCK_STREAM,)) == -)
  16. {
  17. fprintf(stderr,"socket fail,error %s\n",strerror(errno));
  18. return -;
  19. }
  20. bzero(&client_in,sizeof(client_in));
  21. client_in.sin_family = AF_INET;
  22. client_in.sin_port = htons(PORT);
  23. inet_pton(AF_INET,IP,&client_in.sin_addr);
  24. connect(sockfd,(struct sockaddr*)&client_in,sizeof(client_in)) ;
  25. return sockfd;
  26. }
  27. static void connect_server(int sockfd)
  28. {
  29. int epollfd;
  30. struct epoll_event events[_EVENTS];
  31. epollfd = epoll_create(EPOLLEVENTS);
  32. char buf[maxn];
  33. int conn;
  34. memset(buf,'\0',sizeof(buf));
  35. add_event(epollfd,STDIN_FILENO,EPOLLIN);
  36. for(;;)
  37. {
  38. fprintf(stderr,"Please input message!\n");
  39. conn = epoll_wait(epollfd,events,_EVENTS,-);
  40. submit_to_check(epollfd,events,conn,sockfd,buf);
  41. }
  42. close(epollfd);
  43. }
  44. static void submit_to_check(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf)
  45. {
  46. int i;
  47. int fd;
  48. for(i=;i<num;i++)
  49. {
  50. fd = events[i].data.fd;
  51. if(events[i].events & EPOLLIN)
  52. {
  53. submit_to_read(epollfd,fd,sockfd,buf);
  54. }
  55. else if(events[i].events & EPOLLOUT)
  56. {
  57. submit_to_write(epollfd,fd,sockfd,buf);
  58. }
  59. }
  60. }
  61. static void submit_to_read(int epollfd,int fd,int sockfd,char *buf)
  62. {
  63. memset(buf,'\0',sizeof(buf));
  64. int n;
  65. n = read(fd,buf,maxn);
  66. if(n == )
  67. {
  68. fprintf(stderr,"server close.\n");
  69. close(fd);
  70. }
  71. else if(n == -)
  72. {
  73. perror("read error:");
  74. close(fd);
  75. }
  76. else
  77. {
  78. if(fd == STDIN_FILENO)
  79. add_event(epollfd,sockfd,EPOLLOUT);
  80. else
  81. {
  82. change_delete(epollfd,sockfd,EPOLLIN);
  83. add_event(epollfd,STDOUT_FILENO,EPOLLOUT);
  84. }
  85. }
  86. }
  87. static void submit_to_write(int epollfd,int fd,int sockfd,char *buf)
  88. {
  89. int n;
  90. n = write(fd,buf,strlen(buf));
  91. if(n == -)
  92. {
  93. perror("write error:");
  94. close(fd);
  95. }
  96. else
  97. {
  98. if(fd == STDOUT_FILENO)
  99. {
  100. change_delete(epollfd,fd,EPOLLOUT);
  101. }
  102. else
  103. {
  104. change_event(epollfd,fd,EPOLLIN);
  105. }
  106. }
  107. memset(buf,,sizeof(buf));
  108. }
  109. static void change_event(int epollfd,int sockfd,int ser_event)
  110. {
  111. struct epoll_event eventfd;
  112. eventfd.data.fd = sockfd;
  113. eventfd.events = ser_event;
  114. epoll_ctl(epollfd,EPOLL_CTL_MOD,sockfd,&eventfd);
  115. }
  116. static void change_delete(int epollfd,int sockfd,int ser_event)
  117. {
  118. struct epoll_event eventfd;
  119. eventfd.data.fd = sockfd;
  120. eventfd.events = ser_event;
  121. epoll_ctl(epollfd,EPOLL_CTL_DEL,sockfd,&eventfd);
  122. }
  123.  
  124. static void add_event(int epollfd,int sockfd,int ser_event)
  125. {
  126. struct epoll_event eventfd;
  127. eventfd.data.fd = sockfd;
  128. eventfd.events = ser_event;
  129. epoll_ctl(epollfd,EPOLL_CTL_ADD,sockfd,&eventfd);
  130. }
  131. int main()
  132. {
  133. int sockfd = init();
  134. connect_server(sockfd);
  135. close(sockfd);
  136. return ;
  137. }

多路复用I/O模型epoll() 模型 代码实现的更多相关文章

  1. nginx中的epoll模型

    要了解epoll模型,就要一个一个知识点由浅至深地去探索. 1.IO复用技术 IO流请求操作系统内核,有串行处理和并行处理两种概念. 串行处理是前面一个操作处理地时候,后面的所有操作都需要等待.因此, ...

  2. 多路复用I/O模型poll() 模型 代码实现

    多路复用I/O模型poll() 模型 代码实现 poll()机制和select()机制是相似的,都是对多个描述符进行轮询的方式. 不同的是poll()没有描述符数目的限制. 是通过struct pol ...

  3. Epoll模型详解

    Linux 2.6内核中提高网络I/O性能的新方法-epoll I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数. 1.为什么select落后    首先,在Lin ...

  4. 【转】select和epoll模型的差异

    http://www.cppblog.com/converse/archive/2008/10/12/63836.html epoll为什么这么快 epoll是多路复用IO(I/O Multiplex ...

  5. linux epoll模型

    原文:http://yjtjh.blog.51cto.com/1060831/294119 Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数.Linux ...

  6. (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 ...

  7. 基于EPOLL模型的局域网聊天室和Echo服务器

    一.EPOLL的优点 在Linux中,select/poll/epoll是I/O多路复用的三种方式,epoll是Linux系统上独有的高效率I/O多路复用方式,区别于select/poll.先说sel ...

  8. 并发编程-epoll模型的探索与实践

    前言 我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,sele ...

  9. go标准库I/O模型:epoll+多协程

    本文为linux环境下的总结,其他操作系统本质差别不大.本地文件I/O和网络I/O逻辑类似. epoll+多线程的模型 epoll+多线程模型和epoll 单进程区别.优点     对比于redis这 ...

随机推荐

  1. BZOJ2795/2890/3647 [Poi2012]A Horrible Poem 【字符串hash】

    题目链接 BZOJ2795 BZOJ2890 BZOJ3647 题解 三倍经验! 我们要快速求区间最小循环节 我们知道循环节有如下性质: ①当\(L\)为循环节长度,那么\(s[l...r - L] ...

  2. UVA.674 Coin Change (DP 完全背包)

    UVA.674 Coin Change (DP) 题意分析 有5种硬币, 面值分别为1.5.10.25.50,现在给出金额,问可以用多少种方式组成该面值. 每种硬币的数量是无限的.典型完全背包. 状态 ...

  3. 51nod 1257 背包问题 V3(分数规划)

    显然是分数规划...主要是不会求分数的形式,看了题解发现自己好傻逼QAQ 还是二分L值算出d[]降序选K个,顺便记录选择时候的p之和与w之和就可以输出分数形式了... #include<iost ...

  4. 解决webstrom 输入法光标不跟随问题

    参考博客地址 https://blog.csdn.net/wang414300980/article/details/79537875 原因是jdk版本问题,下载jdk jbsdk8u152b1036 ...

  5. caffe中使用crop_size剪裁训练图片

    layer { name: "data" type: "Data" top: "data" top: "label" i ...

  6. ACE自适配通信环境简介

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/03/580795.html ACE自适配通信环境 (Adaptive Communicatio ...

  7. RotateAnimation 详解

    RotateAnimation 详解 看看新闻网>看引擎>开源产品 其他构造器的旋转也可参考这副图. RotateAnimation旋转坐标系为以旋转点为坐标系(0,0)点.x轴为0度,顺 ...

  8. [技巧篇]03.关于MyBatis的简单批量处理

  9. 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 ...

  10. Android数据过滤器:Filter

    类图: 通常可以将SearchView和ListView结合,实现数据的搜索和过滤. 1.监听SearchView,SearchView.setOnQueryTextListener(OnQueryT ...