当前位置: 首页 > news >正文

网站建立失败的原因是手机浏览器主页网站推荐

网站建立失败的原因是,手机浏览器主页网站推荐,辽宁建设工程信息网ca锁激活,网页设计aiIO多路复用 —— epoll 前言 在之前我们就已经介绍过了select和poll,在作为io多路复用的最后一个的epoll,我们来总结一下它们之间的区别: a select 实现原理 select 通过一个文件描述符集合#xff08;fd_set#xff09;来工作#xff0c;该集合可以包含需要监控的文件…IO多路复用 —— epoll 前言 在之前我们就已经介绍过了select和poll,在作为io多路复用的最后一个的epoll,我们来总结一下它们之间的区别: a select 实现原理 select 通过一个文件描述符集合fd_set来工作该集合可以包含需要监控的文件描述符。调用者会指定一个超时时间如果在这个时间内没有任何描述符准备好则函数返回。select 可以同时监听读、写和异常三种类型的事件。 优点 select 函数调用和实现比较简单同时它支持跨平台 缺点 select是基于位图这一数据结构来存储与遍历文件描述符相关的信息由于位图数据结构的限制select最多能同时监听1024个文件描述符如果超过1024个文件描述符,无法实现大规模的并发处理。 每次调用select需要拷贝位图而且select属于用户态网络通信属于内核态需要拷贝两次会影响select的性能。 select的每次监听都需要遍历一整个位图随着需要监听的socket增加性能会大大下降。 poll 实现原理 poll 通过一个链表来存储需要监控的文件描述符当文件描述符就绪时链表中的节点会被移动到就绪链表中当链表为空时poll会阻塞。poll与select类似也是通过一个文件描述符集合来工作但是poll所使用的数据结构是一个结构体数组它的结构如下: struct pollfd {int fd; //存储的socketshort events; // socket触发的事件short revents; // 返回的事件 }优点 poll 函数调用和实现简单同时它支持跨平台同时相对于selectpoll没有了1024的限制可以实现对更多文件描述符的监听。 缺点 poll监视的连接数没有1024的限制但是随着socket的增多poll的效率会降低无法处理超大规模并发。 epoll epoll的原理 epoll 全名是 eventpoll,是Linux内核2.5.44 版本之后才出现的一个事件通知机制。它属于IO多路复用技术的一种形式,IO多路复用技术指的是一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其进行读写操作。上面的select和poll都具有一个通病,那就是都有性能瓶颈,而epoll可以承受百万级别的连接属于select和poll模式的升级版。 epoll的优点 select和poll监听都是线性检测的而epoll是基于红黑树来管理文件描述符,对于事件的发生它不像select和poll那样需要遍历整个文件描述符集合而是通过回调函数来通知所以epoll的效率更高. select和poll在工作中需要对集合进行判断来看哪些文件描述符已经就绪而epoll则不需要epoll通过回调函数来通知所以epoll的效率更高。 当我们需要监听大量的文件描述符时epoll的效率会更高所以epoll是当前最常用的IO多路复用技术。 epoll的操作函数 在Linux内核中主要给我们提供了一下三个函数来操作epoll: #include sys/epoll.h //创建一个epoll实例,通过红黑树来管理文件描述符 int epoll_create(int size); //管理红黑树中的文件描述符(添加,修改,删除) int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); //等待文件描述符就绪 int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);epoll_create epoll_create函数用于创建一个epoll实例参数size表示要监听的文件描述符的数量但是这个参数在Linux 2.6.8之后已经没有意义了因为epoll的红黑树可以动态扩展所以大于0即可。 int epfd epoll_create(0);返回值: 成功:返回epoll实例的文件描述符失败:返回-1,并设置errno epoll_ctl epoll_ctl函数用于管理红黑树中的文件描述符参数epfd表示epoll实例的文件描述符参数op表示要进行的操作参数fd表示要监听的文件描述符参数event表示要监听的事件。 在epoll中有以下和事件相关的数据结构 typedef union epoll_data {void *ptr;int fd; // 通常情况下使用这个成员, 和epoll_ctl的第三个参数相同即可uint32_t u32;uint64_t u64; } epoll_data_t;struct epoll_event {uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */ }; 而在epool_ctl函数中主要要注意下面几个参数 int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);epfd:epoll实例的文件描述符op:要进行的操作 EPOLL_CTL_ADD:添加文件描述符EPOLL_CTL_MOD:修改文件描述符EPOLL_CTL_DEL:删除文件描述符 fd:要监听的文件描述符event:epoll事件,用来修饰fd,指定检测什么事件 events:事件类型 EPOLLIN:读事件EPOLLOUT: 写事件EPOLLERR: 错误事件 data:用户数据,通常情况下使用fd即可 epoll_wait epoll_wait函数用于等待事件的发生参数epfd表示epoll实例的文件描述符参数events表示要监听的事件参数maxevents表示最多监听多少个事件参数timeout表示等待时间。 int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout);epfd:epoll实例的文件描述符events:要监听的事件maxevents:最多监听多少个事件timeout:等待时间 0函数不阻塞不管epoll实例中有没有就绪的文件描述符函数被调用后都直接返回大于0如果epoll实例中没有已就绪的文件描述符函数阻塞对应的毫秒数再返回-1函数一直阻塞直到epoll实例中有已就绪的文件描述符之后才解除阻塞 epoll的使用 这里为实现了一个简单的基于epoll实现的服务端与客户端通讯大家可以自己测试一下: //server.cpp #include iostream #include unistd.h #include ctype.h #include stdlib.h #include sys/stat.h #include sys/socket.h #include arpa/inet.h #include sys/epoll.h #include string.hint main(int argc,char* argv[]) {if(argc!3){std::cout命令行参数数量不对std::endl;std::cout./demo port timeoutstd::endl;exit(-1);}// 创建套接字int lfdsocket(AF_INET,SOCK_STREAM,0);if(lfd0){perror(create socket);return -1;}//绑定struct sockaddr_in server_addr;memset(server_addr,0,sizeof(server_addr));server_addr.sin_porthtons(atoi(argv[1]));server_addr.sin_familyAF_INET;server_addr.sin_addr.s_addrhtonl(INADDR_ANY);//设置端口复用int opt1;setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,opt,sizeof(opt));//绑定端口int retbind(lfd,(struct sockaddr*)server_addr,sizeof(server_addr));if(ret0){perror(bind);exit(-1);}//监听retlisten(lfd,10);if(ret0){perror(listen);}//创建epoll实例int epfdepoll_create(100);if(epfd0){perror(epfd);exit(-1);}struct epoll_event ev;ev.data.fdlfd;ev.eventsEPOLLIN;retepoll_ctl(epfd,EPOLL_CTL_ADD,lfd,ev);if(ret0){perror(epoll_ctl);}struct epoll_event evs[1024];int size(sizeof(evs)/sizeof(struct epoll_event));while(1){int numepoll_wait(epfd,evs,size,atoi(argv[2]));for(int i0;inum;i){int fdevs[i].data.fd;if(fdlfd) //如果是监听的socket{int cfdaccept(fd,0,0); //接收客户端的连接ev.eventsEPOLLIN;ev.data.fdcfd;int retepoll_ctl(epfd,EPOLL_CTL_ADD,cfd,ev);if(ret0){perror(epoll_ctl);exit(-1);}}else //不是监听的说明要接收客户端的消息{char buffer[1024];memset(buffer,0,sizeof(buffer));int lenrecv(fd,buffer,sizeof(buffer)-1,0);std::coutlenstd::endl;if(len0) //客户端已经断开连接{int retepoll_ctl(epfd,EPOLL_CTL_DEL,fd,NULL);if(ret0){perror(epoll_ctl_del);exit(-1);}close(fd);}else if(len0){std::cout333std::endl;std::coutclient:bufferstd::endl;char* recebufok;send(fd,recebuf,sizeof(recebuf),0);}else{perror(recv);exit(-1);}}}}return 0; }//client.cpp #include iostream #include unistd.h #include ctype.h #include stdlib.h #include sys/socket.h #include arpa/inet.h #include string.hint main(int argc, char* argv[]) {if (argc ! 3) {std::cout 命令行参数数量不对 std::endl;std::cout ./client server_ip port std::endl;return -1;}// 创建套接字int sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd 0) {perror(socket);return -1;}// 设置服务器地址信息struct sockaddr_in server_addr;memset(server_addr, 0, sizeof(server_addr));server_addr.sin_family AF_INET;server_addr.sin_port htons(atoi(argv[2]));if (inet_pton(AF_INET, argv[1], server_addr.sin_addr) 0) {perror(inet_pton);close(sockfd);return -1;}// 连接到服务器if (connect(sockfd, (struct sockaddr*)server_addr, sizeof(server_addr)) 0) {perror(connect);close(sockfd);return -1;}// 发送数据给服务器const char* sendbuf Hello from client!;ssize_t send_len send(sockfd, sendbuf, strlen(sendbuf), 0);if (send_len 0) {perror(send);close(sockfd);return -1;}std::cout Sent: sendbuf std::endl;// 接收服务器的数据char buffer[1024];memset(buffer, 0, sizeof(buffer));ssize_t recv_len recv(sockfd, buffer, sizeof(buffer)-1, 0);if (recv_len 0) {std::cout Received from server: buffer std::endl;} else if (recv_len 0) {std::cout Server closed the connection. std::endl;} else {perror(recv);}// 关闭套接字close(sockfd);return 0; }# makefile all: client serverserver: server.cppg -g -o server server.cppclient: client.cppg -g -o client client.cppepoll的工作模式 epoll有两种工作模式LTLevel Triggered水平触发和ETEdge Triggered边缘触发。 LT模式 LT又叫水平模式,是epoll的默认工作模式。在这种模式下内核会不断地通知你文件描述符是否就绪即使你已经读取了数据。也就是说即使你读取了数据文件描述符仍然被认为是就绪的内核会继续通知你。这种模式适用于需要不断地检查文件描述符是否就绪的场景。 水平模式主要有以下特点: 这是epoll的默认工作模式。在LT模式下当一个文件描述符准备好进行读写操作时epoll会通知应用程序。如果应用程序没有立即处理该事件或者在处理过程中没有完全读取或写入所有数据那么只要文件描述符仍然处于就绪状态epoll将继续通知应用程序。 其实对于大多数应用来说LT模式足够使用并且它的行为与传统的poll和select相似 ET模式 ET又叫边缘模式是epoll的高级模式。在这种模式下内核只会通知你文件描述符从非就绪状态变为就绪状态一次即使你读取了数据文件描述符仍然被认为是非就绪的内核不会继续通知你。这种模式适用于需要高效处理大量并发连接的场景。 边缘模式主要有以下特点: ET模式是一种低延迟、高性能的工作模式。在ET模式下epoll只会在状态发生变化时通知应用程序一次。例如如果一个文件描述符从非就绪变为就绪epoll将通知应用程序但是如果应用程序未能在第一次通知后立即处理完所有可用的数据那么即使该文件描述符仍然是就绪状态epoll也不会再次发送通知直到该文件描述符的状态再次发生变化即从就绪变回非就绪再由非就绪变成就绪。 因此在ET模式下应用程序必须确保每次收到通知时都尽可能多地读取或写入数据以避免错过后续的通知。这通常意味着在循环中尽可能多地尝试读写操作直到遇到EAGAIN或EWOULDBLOCK错误为止这表明当前没有更多可读写的就绪数据。 PS: LT模式会不断通知应用程序即使应用程序已经开始读取数据,这样可以保证应用程序能够及时处理数据但是 频繁的通知会带来性能的损耗而ET模式只会在状态发生变化时通知应用程序一次因此应用程序需要确保每次收到通知时都尽可能多地读取或写入数据以避免错过后续的通知。所以ET模式要求应用程序在每次收到通知时都尽可能多地读取或写入数据否则可能会错过后续的通知。因此ET模式通常需要更复杂的编程逻辑并且对应用程序的设计和实现有更高的要求。 2.我们在使用ET模式要设置EPOLLET标志如下: if(fdlfd) //如果是监听的socket {int cfdaccept(fd,0,0); //接收客户端的连接ev.eventsEPOLLIN|EPOLLET; //设置边沿触发ev.data.fdcfd;int retepoll_ctl(epfd,EPOLL_CTL_ADD,cfd,ev);if(ret0){perror(epoll_ctl);exit(-1);} }3.LT模式下支持阻塞和非阻塞而ET模式下只支持非阻塞。
http://www.zqtcl.cn/news/632549/

相关文章:

  • 毕业设计论文网站开发需要多少湛江建站免费模板
  • 做豆制品的网站集团网站建设策划方案
  • 燕郊网站制作哈尔滨企业网站建站推荐
  • 本地网站做通用会员卡建立电子商务网站目的
  • ftp网站地图怎么做网站模板出售
  • 用rp怎么做网站导航菜单手机app制作入门教程
  • 国外创意网站市场营销在线课程
  • 怎么做点图片链接网站网站建设云解析dns有什么用
  • 重庆网站建设哪家公司哪家好企业 网站规划与网页设计word
  • 手机必备软件100个网站建设和优化排名
  • 天津公司网站怎样制作网页设计图片尺寸
  • 网站建设中模板代码网络营销推广公司哪家好
  • 百度免费建立网站搜索引擎推广效果
  • 网站建设分金手指排名十二建设内容管理网站的目的
  • 无锡网站策划制作网站的工具
  • 免费的网站开发软件百度做网站推广的费用
  • 汽车维修东莞网站建设怎么用阿里的域名 做网站
  • 网站怎么做免费cosy WordPress
  • wordpress 关闭自动更新青岛济南网站建设优化
  • 外贸网站推广平台哪个好如何建设手机端网站
  • linux新建网站巩义网站建设定制
  • 网站建设要什么软件有哪些北京seo
  • 空调设备公司网站建设wordpress 4.9
  • 潮州市网站建设公司网页设计代码模板素材
  • 深圳做网站开发费用个人网页设计作品手绘
  • 怎样做网站跳转国内企业建站模板
  • 优化网站哪个好互联网公司市值
  • 广州微信网站开发游戏企业用什么程序做网站
  • 深圳赶集同城网站建设网站空间类型
  • 怎么样做网站代wordpress手机上传图片插件