任务:

实现一个TCP server的回声服务器,功能是将客户端发送的消息原样返回,应用epoll处理事件循环实现IO多路复用。借此任务理解IO多路复用应用的开发模式。

参考资料:

http://man7.org/linux/man-pages/man2/epoll_create1.2.html

http://man7.org/linux/man-pages/man2/epoll_wait.2.html

http://man7.org/linux/man-pages/man2/epoll_ctl.2.html

代码实现:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/epoll.h>#define LISTEN_BACKLOG 50
#define BUFFER_SIZE 1024
#define MAX_EVENTS 1024typedef struct efddata{void * ptr;int fd;uint64_t len;
} efd_data;int main(int argc,char* argv[]){int sfd,cfd,epfd,nfds,n,r,w;char* buf[MAX_EVENTS];struct sockaddr_in addr_in = {0};// 创建epollepfd = epoll_create1(EPOLL_CLOEXEC);printf("epfd: %d\n",epfd);if (epfd == -1){perror("epoll_create1 fail");exit(EXIT_FAILURE);}// 创建监听socketsfd = socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,0);printf("sfd: %d\n",sfd);if (sfd == -1){perror("socket fail");exit(EXIT_FAILURE);}addr_in.sin_family = AF_INET;addr_in.sin_port = htons(80);if(bind(sfd,(const struct sockaddr*)&addr_in,sizeof(struct sockaddr_in)) == -1){perror("bind fail");exit(EXIT_FAILURE);}if(listen(sfd,LISTEN_BACKLOG) == -1){perror("listen fail");exit(EXIT_FAILURE);}// 将监听socket的EPOLLIN事件加入队列struct epoll_event evt = {0};evt.events = EPOLLIN;evt.data.fd = sfd;if(epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&evt) == -1){perror("epoll_ctl add epfd fail");exit(EXIT_FAILURE);}// 预分配fd事件内存struct epoll_event events[MAX_EVENTS],*fdevents[MAX_EVENTS];for(n = 0; n < MAX_EVENTS; ++n){struct epoll_event *e = (struct epoll_event *)malloc(sizeof(struct epoll_event));if(e == NULL){perror("malloc");exit(EXIT_FAILURE);}fdevents[n] = e;}for(;;){nfds = epoll_wait(epfd,events,MAX_EVENTS,-1);if(nfds == -1){perror("epoll_wait fail");close(epfd);exit(EXIT_FAILURE);}for(n = 0; n < nfds; ++n){if(events[n].data.fd == sfd){ // 接受客户端连接cfd = accept(sfd,NULL,NULL);if (cfd == -1){fprintf(stderr,"accept fail %d\n",sfd);continue;}char * rbuf = (char *)malloc(BUFFER_SIZE);buf[cfd] = rbuf;efd_data* data = (efd_data *)malloc(sizeof(efd_data));data->ptr = buf[cfd];data->fd = cfd;struct epoll_event *e = fdevents[cfd];e->events = EPOLLIN;e->data.ptr = data;if(epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,fdevents[cfd]) == -1){perror("epoll_ctl add fail");close(cfd);}fprintf(stdout,"accept cfd %d\n",cfd);}else{efd_data * data = (efd_data *)events[n].data.ptr; // 处理读事件if(events[n].events & EPOLLIN){fprintf(stdout,"epollin ready cfd %d\n",data->fd);r = read(data->fd,data->ptr,BUFFER_SIZE);if(r == -1){perror("read fail");if(epoll_ctl(epfd,EPOLL_CTL_DEL,data->fd,NULL) == -1){perror("epoll_ctl del fail");exit(EXIT_FAILURE);;}close(data->fd);}else{struct epoll_event *evt = fdevents[data->fd];evt->events = EPOLLOUT;((efd_data *)(evt->data.ptr))->len= r;if(epoll_ctl(epfd,EPOLL_CTL_MOD,data->fd,evt) == -1){perror("epoll_ctl mod epollout fail");}}}// 处理写事件if(events[n].events & EPOLLOUT){w = write(data->fd,data->ptr,data->len);if(w == -1){fprintf(stderr,"write fail to cfd:%d\n",data->fd);}epoll_ctl(epfd,EPOLL_CTL_DEL,data->fd,NULL);close(data->fd);fprintf(stdout,"write success cfd: %d\n",data->fd);}}}}}

View Code

可以用go写一个tcp的客户端,模拟并发访问。

package mainimport ("flag""fmt""log""net""sync"
)var wg sync.WaitGroup
func testEcho(n int) {defer wg.Done()con, err := net.Dial("tcp", "[192.168.171.134]:80")if err != nil {log.Fatal(err)}defer con.Close()msg := fmt.Sprintf("Hello epoll %d~", n)l, err := con.Write([]byte(msg))if err != nil {log.Fatal(err)}buffer := make([]byte, 1024)l, err = con.Read(buffer)if err != nil {log.Fatal(err)}log.Println(string(buffer[0:l]))
}var n = flag.Int("n", 100, "set the max test count")func main() {flag.Parse()log.Println("start\n")for i := 0; i < *n; i++ {wg.Add(1)go testEcho(i)}wg.Wait()log.Println("End\n")
}

View Code

执行效果:

经过这个过程,可以更加深刻的理解epoll的工作原理,对于理解redis和nginx的IO多路复用机制很有帮助~

转载于:https://www.cnblogs.com/ling-diary/p/10622368.html

基于epoll实现一个IO多路复用的回声服务器相关推荐

  1. 引入了一个IO多路复用模型

    我们前面讲的非阻塞仍然需要进程不断的轮询重试.能不能实现当数据可读了以后给程序一个通知呢?所以这里引入了一个IO多路复用模型,I/O多路复用的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可 ...

  2. 聊一个不常见的面试题:为什么数据库连接池不采用 IO 多路复用?

    欢迎关注方志朋的博客,回复"666"获面试宝典 今天我们聊一个不常见的 Java 面试题:为什么数据库连接池不采用 IO 多路复用? 这是一个非常好的问题.IO多路复用被视为是非常 ...

  3. NIO详解(三):IO多路复用模型之select、poll、epoll

    1. 前言 最近在研究基于Java的高性能异步非阻塞I/O框架Netty,因为最近做的RDMAChannel要用到其中的思想.Netty底层是通过大量的NIO实现的,通过分析底层NIO源码,发现NIO ...

  4. IO多路复用 select、poll、epoll

    什么是IO多路复用 在同一个线程里面, 通过拨开关的方式,来同时传输多个(socket)I/O流. 在英文中叫I/O multiplexing.这里面的 multiplexing 指的其实是在单个线程 ...

  5. io多路复用的原理和实现_IO多路复用的三种机制:select 、poll 、epoll

    目录 概述 IO多路复用本质 IO多路复用的优势 IO多路复用Select机制 IO多路复用Poll机制 IO多路复用Epoll机制 select,poll,epoll机制区别总结 php7进阶到架构 ...

  6. html select选择事件_一道搜狗面试题:IO多路复用中select、poll、epoll之间的区别...

    (1)select==>时间复杂度O(n) 它仅仅知道了,有I/O事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对 ...

  7. 【python】-- IO多路复用(select、poll、epoll)介绍及实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

  8. IO多路复用中select、poll、epoll之间的区别

    本文来说下IO多路复用中select.poll.epoll之间的区别 文章目录 什么是IO多路复用 为什么有IO多路复用机制 同步阻塞(BIO) 同步非阻塞(NIO) IO多路复用(现在的做法) 3种 ...

  9. python io多路复用_【python】-- IO多路复用(select、poll、epoll)介绍及实现

    IO多路复用(select.poll.epoll)介绍及select.epoll的实现 IO多路复用中包括 select.pool.epoll,这些都属于同步,还不属于异步 一.IO多路复用介绍 1. ...

最新文章

  1. MySQL5.5编译安装
  2. Java设计模式(二十):中介者设计模式
  3. spark向量矩阵的使用(scala)
  4. Python 常用函数 configparser模块
  5. php mysql 常用语句_PHP mysql基本语句指令
  6. maven的eclipse找不到本地仓库的的jar包
  7. 避免数据二次提交的处理方式
  8. ubuntu16.04 装机4:安装防火墙ufw
  9. 奎享添加自己字体_奎享雕刻软件写字操作简要说明
  10. hbase的快速下载
  11. 已知鸡兔共35只c语言,行测数量关系技巧:巧解鸡兔同笼问题
  12. linux ftp解压命令 cannot fid or open,CPAN命令操作细节
  13. 阿里在线免费图标库的使用
  14. 2021最新chrome浏览器与chromedriver版本对照表
  15. 请介绍一下三地菩萨,再说一说,要证悟什么才能称之为三地菩萨.谢谢.
  16. 刘润商业洞察力学习笔记1
  17. 飞机上的飞行数据记录处理运算 ReXgen 2 IMU:达到新的高度 惯性导航 航位运算
  18. PyGmae:有限状态机实践(十三)
  19. C++基础-介绍·数据结构·排序·算法
  20. 数字疗法002 | 睡不着,睡不醒,睡不好?这几个平台是失眠星人的救星

热门文章

  1. python3.8安装pip-MAC本安装python3.8后,pip3命令无法更新问题
  2. python语言if语句-python的if语句
  3. python while循环语句-Python
  4. windows 10 python哪个版本的好-windows支持哪个版本的python
  5. python能在工程上干嘛-python能干什么?
  6. python学习软件-学习python用什么软件
  7. 不使用vue-cli来创建项目
  8. LeetCode Find All Numbers Disappeared in an Array
  9. 题目1024:畅通工程
  10. 人要有水的精神和树的精神