epoll高并发多路复用,基于epoll的高性能服务器

简介:

              并发测试工具ab使用


linux命令安装这个工具:apt-get install apache2

windows中装好apache之后就会再带一个工具

wKiom1lsa93hTmbcAAF9M0dvpaI538.png-wh_50


wKiom1lsbH2h60kcAADUGP_O-ng619.png-wh_50

windows命令使用方法

ab -n 200 -c 5 http://www.baidu.com/

1000就是测试的数量

-c 10 就是开启的线程数

 测试的地址

wKiom1lsbdbQC6xuAABtIfJaNTE882.png-wh_50

反回了一些测试信息,如 使用时间,每次要多久等信息。


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使用)

1
#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要设置成非阻塞的.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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上使用

wKioL1lshKzw1X-mAAMS4u5CT7k476.png-wh_50


当我们发现他发送的X,表示整个的多路复用的程序就运行起来了,

在用一个工具来测试一下,

ab -n 1000 -c 10 192.168.1.125:15988/

wKiom1lsjDTC7L_IAAFmup9c5dE656.png-wh_50


apache测试出的吞吐率为Requests per second:10102.54[#/sec](mean)

每秒请求达到上万

wKioL1lsjkji1LqJAAGFM61MZaM979.png-wh_50




 本文转自超级极客51CTO博客,原文链接:http://blog.51cto.com/12158490/1948310,如需转载请自行联系原作者





相关文章
|
2月前
|
网络协议 安全 测试技术
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
手撕测试tcp服务器效率工具——以epoll和io_uring对比为例
40 2
|
3月前
|
API C++
socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现(1)
前言   本文旨在学习socket网络编程这一块的内容,epoll是重中之重,后续文章写reactor模型是建立在epoll之上的。
34 0
|
3月前
|
监控 安全 Linux
socket编程之常用api介绍与socket、select、poll、epoll高并发服务器模型代码实现(3)
高并发服务器模型-poll poll介绍   poll跟select类似, 监控多路IO, 但poll不能跨平台。其实poll就是把select三个文件描述符集合变成一个集合了。
35 0
|
14天前
|
存储 缓存 NoSQL
Redis 服务器指南:高性能内存数据库的完整使用指南
Redis 服务器指南:高性能内存数据库的完整使用指南
|
1月前
|
编解码 分布式计算 网络协议
一文让你深入了解 Java-Netty高性能高并发
一文让你深入了解 Java-Netty高性能高并发
48 1
|
2月前
|
存储 缓存 网络协议
Go语言并发编程实战:构建高性能Web服务器
【2月更文挑战第6天】本文将通过构建一个高性能的Web服务器实战案例,深入探讨如何在Go语言中运用并发编程技术。我们将利用goroutine和channel实现高效的请求处理、资源管理和并发控制,以提升Web服务器的性能和稳定性。通过这一实战,你将更好地理解和掌握Go语言在并发编程方面的优势和应用。
|
2月前
|
存储 缓存 物联网
DP读书:鲲鹏处理器 架构与编程(二)服务器与处理器——高性能处理器的并行组织结构、ARM处理器
DP读书:鲲鹏处理器 架构与编程(二)服务器与处理器——高性能处理器的并行组织结构、ARM处理器
249 0
|
2月前
|
存储 负载均衡 监控
epoll服务器百万并发测试
epoll服务器百万并发测试
31 1
|
2月前
|
弹性计算 安全 数据中心
阿里云香港服务器提供高性能、安全、CN2高速网络、BGP多线精品
阿里云香港服务器提供高性能、安全、CN2高速网络、BGP多线精品
|
2月前
|
前端开发 Java API
构建异步高并发服务器:Netty与Spring Boot的完美结合
构建异步高并发服务器:Netty与Spring Boot的完美结合