首页 > 代码库 > epoll高并发多路复用,基于epoll的高性能服务器
epoll高并发多路复用,基于epoll的高性能服务器
并发测试工具ab使用
linux命令安装这个工具:apt-get install apache2
windows中装好apache之后就会再带一个工具
windows命令使用方法
ab -n 200 -c 5 http://www.baidu.com/
1000就是测试的数量
-c 10 就是开启的线程数
测试的地址
反回了一些测试信息,如 使用时间,每次要多久等信息。
linux也是一样用的。
epoll多路复用IO 高并发
epoll多路复用是专门用来处理高并发的,在linux多路复用中有多种,
有epoll,select,其中select是在linux和windows中通用的,其中select用来做过超时处理,本身多路复用,为了高并发,目前只推荐
使用epoll在linux中,因为其他方案没有他的效率高,而且代码复杂度
不比他简单,epoll主要解决的问题是:
处理大量并发连接中,只有少量活跃的,(就是很多人连接过来,但是他们都没有断开)只有少数是活跃的, 如果都活跃那epoll也没提高效率.
web服务器处理的并发数量是有限的。
epoll连接有两种方式:一种是水平触发,LT(level triggered)他其实和select一样,有一个区别是select他是要遍历所有的路判断值,然后会导开销很大, 他的效率好select差不多.
还有一种是边缘触发,(edge-triggered)数据发生变化,有一个数据进来,它就会触发。
代码演示.
在acceppt这里每次都开一个线程,现在先不开线程了,先在一个线程中把所有的处理掉,通过多路复用实现这个功能.
多路复用头文件:(只能在linux使用)
#include<sys/epoll.h>
基于epoll的高性能服务器。开发和高并发测试
里面都有注释:1 创建一个epoll 里面最多放256个套接字,然后注册事件(一个结构体)2确定把哪个socket注册到事件当中,这个是创建的socket用来做服务端的socket。3指定类型 EPOLLIN是数据进来的时候 EPOLLET 边缘触发模式 4把socket注册到epoll里面 EPOLL_CTL_ADD新增 一个socket到epoll当中 5//最多等待20个事件epoll_event event[20];
//发送发一个数据给客户端 意思大盖就是发送一个X给连接客户端
后面将HTTP协议,const char *msga = "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\nX";
等待 判断他是否有数据 20是最多等待20个事件.最后是超时时间 500毫秒int count = epoll_wait(epfd,event, 20, 500);
如果当前等待成功就会遍历当前的socket,
然后判断是哪种socket类型,如果是和客户进行连接的那就接收用户的
数据,并存储用户收发数据的socket,然后注册到epoll当中.
(短连接技术)
如果是与客户收发数据的socket那就调用发送接收接口,并且从client
中删掉这个socket, 因为以及用不到他了,等待下次连接上来的时候
就还需要accpet 进行边缘触发,就是这个原理>
如果发送两次.同时连接呢,ET边缘检查他只会产生一次,
这样会造成Accept被丢掉了,没处理到,所以和客户端bind的socket要设置成非阻塞的.
int main(int argc, char *argv[]) { printf("RUN"); unsigned short port = 15987; XTCP server; printf("Bind"); if (!server.Bind(port)) { printf("Bind error:%d", port); return -1; } printf("Bind ok %d",port); //单线程测试 //1 创建一个epoll 里面最多放256个套接字 int epfd = epoll_create(256); //注册事件 一个结构体 epoll_event ev; //确定把哪个socket注册到事件当中, //这个是创建的socket用来做服务端的socket ev.data.fd = server.m_sock; //指定类型 EPOLLIN是数据进来的时候 EPOLLET 边缘触发模式 ev.events = EPOLLIN | EPOLLET; //2 把socket注册到epoll里面 EPOLL_CTL_ADD新增 一个socket到epoll当中 epoll_ctl(epfd, EPOLL_CTL_ADD, server.m_sock, &ev); //最多等待20个事件 epoll_event event[20]; char buf[1024] = { 0 }; //发送发一个数据给客户端 const char *msga = "HTTP/1.1 200 OK\r\nContent-Length: 1\r\n\r\nX"; int sizeaa = strlen(msga); //如果发送两次 同时连接呢 ET边缘检查他只会产生一次 //这样会造成Accept被丢掉了,没处理到 所以和客户端bind的socket要设置称非阻塞的 server.SetBlock(false); for (;;) { //3 等待 判断他是否有数据 最后是超时时间 int count = epoll_wait(epfd,event, 20, 500); if (count <= 0) continue; //超时直接进入下一次 //变量所有事件 可能有建立连接 或 产生数据 怎么区分呢 for (int i = 0; i<count; i++) { memset(buf, 0, sizeof(buf)); //用来建立连接的socket if (event[i].data.fd == server.m_sock) { ///如果发送两次 同时连接呢 ET边缘检查他只会产生一次 //这样会造成Accept被丢掉了,没处理到 所以和客户端bind的socket要设置称非阻塞的 //死循环 读到返回空为止 for(;;) { XTCP client = server.Accept(); if(client.m_sock <= 0)break; //处理了所有accept //产生一个新的socket注册到epoll当中 ev.data.fd = client.m_sock; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_ADD, client.m_sock, &ev); } } else { //对应的就是客户端的连接 XTCP client; //取出socket值 client.m_sock = event[i].data.fd; //接受 信息 client.Recv(buf, 1024); // http只会发一次, 所以他不会多次数据没处理 //发送 信息 EPOLL_CTL_DEL删掉就行了 client.Send(msga, sizeaa); epoll_ctl(epfd, EPOLL_CTL_DEL, client.m_sock, &ev); client.Close(); } } //创建线程 // TcpThread *th = new TcpThread(); // th->client = client; // std::thread sthr(&TcpThread::Main, th); // // 释放主线程占用的资源 // sthr.detach(); } server.Close(); printf("getchar()"); getchar(); return 0; }
注意左边的知识代码 因为Epoll只能在; linux上使用
当我们发现他发送的X,表示整个的多路复用的程序就运行起来了,
在用一个工具来测试一下,
ab -n 1000 -c 10 192.168.1.125:15988/
apache测试出的吞吐率为Requests per second:10102.54[#/sec](mean)
每秒请求达到上万
本文出自 “12148490” 博客,请务必保留此出处http://12158490.blog.51cto.com/12148490/1948310
epoll高并发多路复用,基于epoll的高性能服务器