1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C++socket编程(六):6.4 epoll多路复用IO高并发

C++socket编程(六):6.4 epoll多路复用IO高并发

时间:2020-06-28 04:54:38

相关推荐

C++socket编程(六):6.4 epoll多路复用IO高并发

现在开始讲讲linux中epoll多路复用高并发

多路复用常用的有epoll,select等,前面已经讲过select处理延时阻塞的问题。而且时在windows上和linux上通用的。

重点:目前在linux中,只推荐用epoll处理多路复用的问题。其他方案,效率没他高而且,代码也不简单。

epoll处理那些问题:

·大量并发连接中只有少量活跃。

·LT(水平触发)(level triggered)

解释:与select一样,与select性能区别,要遍历所有的值,与会导致效率较低。

·ET(边缘触发)(edge-triggered)

解释:只是当数据发生了变化,才会触发一次。每一次触发之后需要将所有数据收完之后在做下一次处理。

如下代码:

整个流程分为三步:

一:创建epoll

二:注册事件

三:边缘检测(我们以ET为例)

//一:创建epoll,epoll_create()int epfd = epoll_create(256); //意思是创建一个epoll里面最多放256个套接字//二:注册事件:epoll_event ev;ev.data.fd = server.sock; //确定把哪一个socket注册到事件中去,就是刚刚创建的socket,做服务端的socketev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD,server.sock,&ev); // 这样就把监听端口的socket注册到了epoll中epoll_event event[20];//这次最多等待20个事件,就会返回,满了需要下次调用char buffer[1024] = { 0 };const char* message = "HTTP/1.1 200 OK\r\nContent-Length:8\r\n\r\nILOVEYOU";int size = strlen(message);for (;;){//三:边缘检测int count = epoll_wait(epfd,event, 20, 500);if (count <= 0)continue;for (int i = 0; i < count; i++){//每次长生的事件可能不只一个,产生的事件,产生的事件无法两种,建立连接,数据传输// 所以我们应该遍历处理,而且接下来的内容,//后面的章节将会用到http进行处理,if (event[i].data.fd == server.sock) //表示接收连接事件{XTcp client = server.Accept(); //接收到一个连接进来,产生一个新的socket,//我们仍然需要将他注册到epoll中ev.data.fd = client.sock;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD, client.sock, &ev); //第二个参数对应的accept时与客户端建立连接后创建的新的socket//如果这么一直注册下去能容纳的256个事件一定会满,所以要清理}else{XTcp client;client.sock = event[i].data.fd;//做模拟http协议的操作client.Recv(buffer, 1024);client.Send(message, size);epoll_ctl(epfd, EPOLL_CTL_DEL,client.sock, &ev);client.Close();}}

我们用ab工具测试下连接

ab -n 1000 -c 10 http://192.168.16.223:8888为例

发现测试卡死。分析原因

XTcp client = server.Accept(); 因为我们时ET模式,但是完全有可能时来了两个socket,两个事件同时来了,但是触发了一次边缘检测。

改后代码:

//一:创建epoll,epoll_create()int epfd = epoll_create(256); //意思是创建一个epoll里面最多放256个套接字//二:注册事件:epoll_event ev;ev.data.fd = server.sock; //确定把哪一个socket注册到事件中去,就是刚刚创建的socket,做服务端的socketev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD,server.sock,&ev); // 这样就把监听端口的socket注册到了epoll中epoll_event event[20];//这次最多等待20个事件,就会返回,满了需要下次调用char buffer[1024] = { 0 };const char* message = "HTTP/1.1 200 OK\r\nContent-Length:8\r\n\r\nILOVEYOU";int size = strlen(message);server.SetBlock(false);for (;;){//三:边缘检测int count = epoll_wait(epfd,event, 20, 500);if (count <= 0)continue;for (int i = 0; i < count; i++){//每次长生的事件可能不只一个,产生的事件,产生的事件无法两种,建立连接,数据传输// 所以我们应该遍历处理,而且接下来的内容,//后面的章节将会用到http进行处理,if (event[i].data.fd == server.sock) //表示接收连接事件{for (;;)//无限循环,读到返回为空为止{XTcp client = server.Accept(); //接收到一个连接进来,产生一个新的socket,//我们仍然需要将他注册到epoll中if (client.sock <= 0)break;ev.data.fd = client.sock;ev.events = EPOLLIN | EPOLLET;epoll_ctl(epfd, EPOLL_CTL_ADD, client.sock, &ev); //第二个参数对应的accept时与客户端建立连接后创建的新的socket//如果这么一直注册下去能容纳的256个事件一定会满,所以要清理}}else{XTcp client;client.sock = event[i].data.fd;//做模拟http协议的操作client.Recv(buffer, 1024);client.Send(message, size);epoll_ctl(epfd, EPOLL_CTL_DEL,client.sock, &ev);client.Close();}}}

ab工具测试结果

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。