首页 > 其他分享 >ohohoh--IO多路复用之最后一个epoll

ohohoh--IO多路复用之最后一个epoll

时间:2024-05-09 23:56:12浏览次数:15  
标签:多线程 epoll -- ohohoh 阻塞 模式 int include

通知:epoll是仅限于在Linux上的函数->其正常流程可参考其他的,这里不多赘述,我主要想说的是非阻塞的套接字边缘模式多线程epoll(很绕,我懂)。。。
先上源代码

#include <iostream>
#include <string.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
	//创建监听套接字
	int lfd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==lfd){
		std::cerr<<"socket error..."<<std::endl;
		exit(1);
	}
	struct sockaddr_in serv_addr;
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_port=htons(9999);
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	//绑定端口
	int ret=bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
	if(-1==ret){
		std::cerr<<"bind error..."<<std::endl;
		close(lfd);
		exit(1);
	}

//监听
int lis_;
lis_=listen(lfd,64);
if(-1==lis_){
    std::cerr<<"lsiten error..."<<std::endl;
    close(lfd);
    exit(1);
}

//创建一个epoll模型
int epfd=epoll_create(100);
if(-1==epfd){
    std::cerr<<"epoll_create error..."<<std::endl;
    close(lfd);
    exit(1);
}
//往epoll实例中添加需要检测的节点,现在只有监听的文件描述符
struct epoll_event ev;
ev.events=EPOLLIN;  //读取 读缓冲区是否有数据
ev.data.fd=lfd;
int temp1=epoll_ctl(epfd,EPOLL_CTL_ADD,lfd,&ev);
if(-1==temp1){
    std::cerr<<"epoll_ctl of lfd error..."<<std::endl;
    close(lfd);
    exit(1);
}

struct epoll_event evs[1024];
int size=sizeof(evs)/sizeof(struct epoll_event);
//持续检测
while(1){
    //调用一次,检测一次
    int num=epoll_wait(epfd,evs,size,-1);
    for(int i=0;i<num;++i){
        int curfd=evs[i].data.fd;   //取出当前的文件描述符
        if(curfd==lfd){ //检测到监听描述符的缓冲区有变化
            int cfd=accept(curfd,nullptr,nullptr);
            //为了配合边缘模式循环读取数据而不阻塞(防止recv空数据阻塞)
            int flag=fcntl(curfd,F_GETFL);
            flag|=O_NONBLOCK;//非阻塞
            fcntl(curfd,F_SETFL,flag);
            //正常操作
            //将得到的新的文件描述符加入epoll模型中,下一轮调用即可检测了
            ev.events=EPOLLIN | EPOLLET;  //读取读缓冲区 | 边缘模式
            ev.data.fd=cfd;
            temp1=epoll_ctl(epfd,EPOLL_CTL_ADD,cfd,&ev);
            if(-1==temp1){
                std::cerr<<"epoll_ctl of "<<i<<" times error..."<<std::endl;
                continue;
            }
        }
        else{
            //循环读取数据
            //处理通信的文件描述符
            char buf[1024];
            while(1){
                memset(buf,0,sizeof(buf));
                int len=recv(curfd,buf,sizeof(buf),0);
                if(0==len){
                    std::cout<<"客户端已经断开连接..."<<std::endl;
                    epoll_ctl(epfd,EPOLL_CTL_DEL,curfd,NULL);
                    close(curfd);
                }
                else if(len>0){
                    std::cout<<"客户端says:"<<buf<<std::endl;
                    send(curfd,buf,len,0);
                }
                else{
                    if(errno==EAGAIN){
                        std::cout<<"数据已经读取完成,缓冲区数据已经为空..."<<std::endl;
                        break;
                    }
                    std::cerr<<"curd:"<<curfd<<" "<<"recv error..."<<std::endl;
                    continue;
                }
            }
        }

    }

}
	close(lfd);
}

注意:这里的epoll搭配多线程应该可以实现百万并发,哪里采用多线程就不赘述了。
注意点①:非阻塞的套接字:

int cfd=accept(curfd,nullptr,nullptr);
//为了配合边缘模式循环读取数据而不阻塞(防止recv空数据阻塞)
int flag=fcntl(curfd,F_GETFL);
flag|=O_NONBLOCK;//非阻塞
fcntl(curfd,F_SETFL,flag);

注意点②:边缘模式(啥是边缘模式,啥是水平模式,建议自己补充)

ev.events=EPOLLIN | EPOLLET;  //读取读缓冲区 | 边缘模式

我没贴多线程的(其实是懒得写了。。。)
over!!!

标签:多线程,epoll,--,ohohoh,阻塞,模式,int,include
From: https://www.cnblogs.com/LLJR/p/18183357

相关文章

  • 《编译原理》阅读笔记:p4-p17
    《编译原理》学习第2天,p4-p17总结,总计14页。一、技术总结1.structureofcompiler编译器组成包括:LexicalAnalyzer->SyntaxAnalazer->Semantictree->IntermediateCodeGenerator->Machine-IndependentCodeOptimizer->CodeGenerator->Machine-Dependent......
  • 【专题】2022年中国企业数字化学习行业研究报告PDF合集分享(附原数据表)
    报告链接:http://tecdat.cn/?p=32263多变,不确定性,复杂,模糊不清的新业务图景,加快了公司人才发展模式的数字化转变;疫情冲击离线运输与公司现金流量,消费者支出减少,机构表现受压,数字化学习突破;行业数字化水平不断提高,商业体系和学习体系之间的关联性不断加强,企业学情图谱不断完善; 阅......
  • 【专题】展望人工智能银行:当银行遇到AI报告PDF合集分享(附原数据表)
    原文链接:http://tecdat.cn/?p=32210在2016年,AlphaGo机器人打败了18届世界棋王李世石,成为了世界棋坛上最伟大的人物。阅读原文,获取专题报告全文,解锁154份文末人工智能银行相关报告。围棋是一种非常复杂的棋类,它要求有很强的直觉,想像力和策略性的思考,而这一切在很长一段时间里都......
  • WinBUGS对多元随机波动率模型:贝叶斯估计与模型比较
    原文链接:http://tecdat.cn/?p=5312原文出处:拓端数据部落公众号  在本文中,我们通过一个名为WinBUGS的免费贝叶斯软件,可以很容易地完成基于似然的多变量随机波动率(SV)模型的估计和比较。通过拟合每周汇率的双变量时间序列数据,多变量SV模型,包括波动率中的格兰杰因果关系,时变相关......
  • Scurm冲刺第四天
    Scurm冲刺第四天1.站立式会议内容昨日已完成任务今日计划完成任务首页代码设计实现前端UI设计代码编写(收藏页面,商品详情页,个人中心页)后端用户功能模块的购物车,收藏和个人中心操作功能后端管理员模块功能实现(登录注册功能,用户管理功能,个人中心操作)跟进前后端......
  • Dubbo和Feign的区别?
    Dubbo和Feign是两个不同的微服务框架,它们在通信协议、服务调用方式、服务注册和发现、服务治理、编程模型以及同步/异步调用等方面存在差异。通信协议:Dubbo使用自定义的RPC协议进行通信,而Feign使用HTTP协议进行通信。服务调用方式:Dubbo采用的是服务间直接的点对点调......
  • P5214 [SHOI2014] 神奇化合物
    题目链接:https://www.luogu.com.cn/problem/P5214题意:给定一张无向图,分别进行以下操作:Q:询问图中有多少连通块;Auv:代表在uv之间链接一条边;Duv:代表删除链接uv的边。做法:考虑到题目数据范围较小,直接用邻接表存边即可。可以发现有些点是不会进行改变的,可以讲在线询问转成......
  • 5.9
    开始学习jetpackcomposeclassMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{BasicsCodelabTheme{//Asurfacecontaine......
  • 单纯形法的平滑分析
    我们采用这样的形式来讨论线性规划:\(\maxc^\topx\)subjectto\(Ax\leqb\),其中\(x,c\in\R^n\),\(A\in\R^{m\timesn},b\in\R^m\)。其中\(P=\{x\midAx\leqb\}\)称为可行域,是\(\R^n\)中的多面体。求解线性规划问题的最常用算法就是单纯形法,它指出我们从\(P\)的一个顶点\(x_......
  • NFLS NOI模拟 序列
    涉及知识点:数论,图论转化建图题意有一串长为\(n\(\leq10^3)\)序列\(a\),给出\(m\(\leq10^3)\)个条件,每条条件形如\(\gcd(a_i,a_j)=k\),问是否存在这样的序列满足所有条件。保证不存在重复的\((a_i,a_j)\)对。思路把题目给出的所有关系建成图,点\(i\)代表\(a_i\),\(\gc......