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

线上销售模式汕头seo网站排名

线上销售模式,汕头seo网站排名,建设门户网站培训通知,2021年10月新闻摘抄前言 作者#xff1a;小蜗牛向前冲 名言#xff1a;我可以接受失败#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话#xff0c;还请点赞#xff0c;收藏#xff0c;关注#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、poll函… 前言 作者小蜗牛向前冲 名言我可以接受失败但我不能接受放弃   如果觉的博主的文章还不错的话还请点赞收藏关注支持博主。如果发现有问题的地方欢迎❀大家在评论区指正   目录 一、poll函数基础知识 1、poll函数接口 2、poll函数多路转接的实现 二、poll服务器的实现  三、epoll函数的基础知识 1、epoll的相关系统调用 2、epoll工作原理 四、epoll服务器  本期学习poll函数的相关接口poll函数是如何实现多路转接的epoll函数的学习epoll函数的工作原理poll函数和epoll函数服务器的实现。 在学习poll和npoll之前我们先来回顾一下select的特点 1. select能同时等待的文件fd是有上限的除非重新改内核否则无法解决 2必须借助第三方数组来维护合法的fd  3. select的大部分参数是输入输出型的调用select前要重新设置所有的fd调用之后我们还有检查更新所有的fd.这带来的就是遍历的成本―--用户 4. select为什么第一个参数是最大fd1呢?确定遍历范围--内核层面 5. select采用位图用户-内核内核-用户来回的进行数据拷贝拷贝成本的问题 更加详细的回顾传送门  为了解决select在IO时会fd上限和每次调用都要重新设定关心fd,所以我们的poll函数就上亮登场了。 一、poll函数基础知识 1、poll函数接口 头文件 #include poll.h函数接口  int poll(struct pollfd *fds, nfds_t nfds, int timeout);参数说明 fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返 回的事件集合.nfds表示fds数组的长度. timeout表示poll函数的超时时间, 单位是毫秒(ms) pollfd 结构体的定义 struct pollfd {int fd; // 文件描述符short events; // 要监视的事件输入short revents; // 实际发生的事件输出 };events 字段是要监视的事件。它是一个位掩码可以包括以下常量之一或多个  OLLIN文件描述符可读。POLLOUT文件描述符可写。POLLPRI文件描述符有紧急数据可读。POLLERR发生错误。POLLHUP文件描述符挂起连接关闭。POLLNVAL文件描述符不是一个打开的文件 revents 字段是实际发生的事件。它是 poll() 函数返回后被填充的字段表示文件描述符上实际发生的事件。 返回结果 返回值小于0, 表示出错;返回值等于0, 表示poll函数等待超时;返回值大于0, 表示poll由于监听的文件描述符就绪而返回 2、poll函数多路转接的实现 多路转接的实现 使用 poll() 函数时通常需要创建一个 pollfd 数组每个元素描述一个要监视的文件描述符及其关注的事件。然后将该数组传递给 poll() 函数并指定超时时间或者设置为 -1 表示永远等待poll() 函数会阻塞直到有事件发生或超时。返回后程序可以检查每个 pollfd 结构体的 revents 字段来判断每个文件描述符上实际发生的事件。 poll的优点 不同与select使用三个位图来表示三个fdset的方式poll使用一个pollfd的指针实现. pollfd结构包含了要监视的event和发生的event不再使用select“参数-值”传递的方式. 接口使用比 select更方便.poll并没有最大数量限制 (但是数量过大后性能也是会下降). poll的缺点  poll中监听的文件描述符数目增多时 和select函数一样poll返回后需要轮询pollfd来获取就绪的描述符.每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中.同时连接的大量客户端在一时刻可能只有很少的处于就绪状态, 因此随着监视的描述符数量的增长, 其效率也会线性下降. 二、poll服务器的实现  pollServer.hpp #pragma once#include iostream #include string #include functional #include poll.h #include sock.hppnamespace poll_ns {static const int defaultport 8081;static const int num 2048;static const int defaultfd -1;using func_t std::functionstd::string(const std::string );class PollServer{public:PollServer(func_t f, int port defaultport) : _func(f), _port(port), _listensock(-1), _rfds(nullptr){}void ResetItem(int i){_rfds[i].fd defaultfd;_rfds[i].events 0;_rfds[i].revents 0;}void initServer(){_listensock Sock::Socket();Sock::Bind(_listensock, _port);Sock::Listen(_listensock);_rfds new struct pollfd[num];for (int i 0; i num; i){ResetItem(i);}_rfds[0].fd _listensock;_rfds[0].events POLLIN;}void Print(){std::cout fd list: ;for (int i 0; i num; i){if (_rfds[i].fd ! defaultfd)std::cout _rfds[i].fd ;}std::cout std::endl;}void Accepter(int listensock){logMessage(DEBUG, Accepter in);// select 告诉我 listensock读事件就绪了std::string clientip;uint16_t clientport 0;int sock Sock::Accept(listensock, clientip, clientport);if (sock 0)return;logMessage(NORMAL, accept success [%s:%d], clientip.c_str(), clientport);// sock我们能直接recv/read 吗不能整个代码只有poll有资格检测事件是否就绪// 将新的sock 托管给poll// 将新的sock托管给poll本质其实就是将sock添加到fdarray数组中即可int i 0;// 找字符集中没有被占用的位置for (; i num; i){if (_rfds[i].fd ! defaultfd)continue;elsebreak;}if (i num){logMessage(WARNING, server if full, please wait);close(sock);}else{_rfds[i].fd sock;_rfds[i].events POLLIN;_rfds[i].revents 0;}Print();logMessage(DEBUG, Accepter out);}void Recver(int pos){logMessage(DEBUG, in Recver);// 读取requestchar buffer[1024];ssize_t s recv(_rfds[pos].fd, buffer, sizeof(buffer) - 1, 0);if (s 0){buffer[s] 0;logMessage(NORMAL, client# %s, buffer);}else if (s 0){close(_rfds[pos].fd);ResetItem(pos);logMessage(NORMAL, client quit);return;}else{close(_rfds[pos].fd);ResetItem(pos);logMessage(ERROR, client quit: %s, strerror(errno));return;}// 2. 处理requeststd::string response _func(buffer);// 3. 返回response// write bugwrite(_rfds[pos].fd, response.c_str(), response.size());logMessage(DEBUG, out Recver);}// 1. handler event rfds 中不仅仅是有一个fd是就绪的可能存在多个// 2. 我们的poll目前只处理了read事件void HandlerReadEvent(){// 遍历fdarray数组for (int i 0; i num; i){// 过滤非法的fdif (_rfds[i].fd defaultfd)continue;if (!(_rfds[i].events POLLIN))continue;if (_rfds[i].fd _listensock (_rfds[i].revents POLLIN))Accepter(_listensock);else if (_rfds[i].revents POLLIN)Recver(i);else{}}}void start(){int timeout -1;for (;;){int n poll(_rfds, num, timeout);switch (n){case 0:logMessage(NORMAL, timeout...);break;case -1:logMessage(WARNING, poll error, code: %d, err string: %s, errno, strerror(errno));break;default:// 说明已经有事情就绪了logMessage(NORMAL, have event ready!);HandlerReadEvent();break;}}}~PollServer(){if (_listensock 0)close(_listensock);if (_rfds)delete[] _rfds;}private:int _port;int _listensock;struct pollfd *_rfds;func_t _func;}; }为了解决pool的缺点程序员们又设计出了npoll 三、epoll函数的基础知识 按照man手册的说法: 是为处理大批量句柄而作了改进的poll. 它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44) 它几乎具备了之前所说的一切优点被公认为Linux2.6下性能最好的多路I/O就绪通知方法 1、epoll的相关系统调用 epoll 有3个相关的系统调用. epoll_create 创建一个epoll的句柄创建了epoll模型 int epoll_create(int size); 自从linux2.6.8之后size参数是被忽略的.用完之后, 必须调用close()关闭 epoll_ct  :epoll的事件注册函数 int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event) 它不同于select()是在监听事件时告诉内核要监听什么类型的事件, 而是在这里先注册要监听的事件类型.第一个参数是epoll_create()的返回值(epoll的句柄).第二个参数表示动作用三个宏来表示.第三个参数是需要监听的fd.第四个参数是告诉内核需要监听什么事件 第二个参数的取值:增改删 EPOLL_CTL_ADD 注册新的fd到epfd中EPOLL_CTL_MOD 修改已经注册的fd的监听事件EPOLL_CTL_DEL 从epfd中删除一个fd struct epoll_event结构如下 typedef union epoll_data {void *ptr;int fd;uint32_t u32;uint64_t u64; } epoll_data_t;struct epoll_event {uint32_t events; // 事件类型输入epoll_data_t data; // 用户数据输出 };poll_data_t 是一个联合体用于在 struct epoll_event 中传递用户数据  events可以是以下几个宏的集合 EPOLLIN : 表示对应的文件描述符可以读 (包括对端SOCKET正常关闭);EPOLLOUT : 表示对应的文件描述符可以写;EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外数据到来); EPOLLERR : 表示对应的文件描述符发生错误;EPOLLHUP : 表示对应的文件描述符被挂断;EPOLLET : 将EPOLL设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.EPOLLONESHOT只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个socket的话, 需要 再次把这个socket加入到EPOLL队列里. epoll_wait收集在epoll监控的事件中已经发送的事件 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 参数events是分配好的epoll_event结构体数组.epoll将会把发生的事件赋值到events数组中 (events不可以是空指针内核只负责把数据复制到这个 events数组中不会去帮助我们在用户态中分配内存).maxevents告之内核这个events有多大这个 maxevents的值不能大于创建epoll_create()时的size.参数timeout是超时时间 (毫秒0会立即返回-1是永久阻塞).如果函数调用成功返回对应I/O上已准备好的文件描述符数目如返回0表示已超时,返回小于0表示函 数失败 2、epoll工作原理 当某一进程调用epoll_create方法时Linux内核会创建一个eventpoll结构体这个结构体中有两个成员与epoll的使用方式密切相关 每一个epoll对象都有一个独立的eventpoll结构体用于存放通过epoll_ctl方法向epoll对象中添加进来的事件这些事件都会挂载在红黑树中如此重复添加的事件就可以通过红黑树而高效的识别出来(红黑树的插入时间效率是lgn其中n为树的高度)而所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系也就是说当响应的事件发生时 会调用这个回调方法这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中 struct eventpoll{ .... /*红黑树的根节点这颗树中存储着所有添加到epoll中的需要监控的事件*/ struct rb_root rbr; /*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/ struct list_head rdlist; .... } 在epoll中对于每一个事件都会建立一个epitem结构体.  struct epitem{ struct rb_node rbn;//红黑树节点 struct list_head rdllink;//双向链表节点 struct epoll_filefd ffd; //事件句柄信息 struct eventpoll *ep; //指向其所属的eventpoll对象 struct epoll_event event; //期待发生的事件类型 } 当调用epoll_wait检查是否有事件发生时只需要检查eventpoll对象中的rdlist双链表中是否有epitem 元素即可.如果rdlist不为空则把发生的事件复制到用户态同时将事件数量返回给用户. 这个操作的时间复杂度 是O(1).  总结一下, epoll的使用过程就是三部曲: 调用epoll_create创建一个epoll句柄;调用epoll_ctl, 将要监控的文件描述符进行注册;调用epoll_wait, 等待文件描述符就绪 epoll的优点(和 select 的缺点对应)  接口使用方便: 虽然拆分成了三个函数, 但是反而使用起来更方便高效. 不需要每次循环都设置关注的文件描述符, 也做到了输入输出参数分离开数据拷贝轻量: 只在合适的时候调用 EPOLL_CTL_ADD 将文件描述符结构拷贝到内核中, 这个操作并不频 繁(而select/poll都是每次循环都要进行拷贝)事件回调机制: 避免使用遍历, 而是使用回调函数的方式, 将就绪的文件描述符结构加入到就绪队列中, epoll_wait 返回直接访问就绪队列就知道哪些文件描述符就绪. 这个操作时间复杂度O(1). 即使文件描述 符数目很多, 效率也不会受到影响.没有数量限制: 文件描述符数目无上限 epoll工作方式  感性理解 你是一个网瘾少年, 天天就喜欢呆在自己的房间玩游戏你妈饭做好了, 喊你吃饭的时候有两种方式: 1. 如果你妈喊你一次, 你没动, 那么你妈会继续喊你第二次, 第三次...还有一种可能是你吃了一口又继续去玩你妈过一会又会开始喊你吃饭直到你下来把饭吃完( 水平触发)2. 如果早上你妈喊你一次, 你没动你妈就不管你了到了下午又吃饭了你妈又会叫你一次没来你妈也不管你到了晚上...(边缘触发) epoll有2种工作方式-水平触发(LT)和边缘触发(ET) 水平触发Level Triggered 工作模式 epoll默认状态下就是LT工作模式 当epoll检测到socket上事件就绪的时候, 可以不立刻进行处理. 或者只处理一部分.如上面的例子你妈喊你吃饭类似, 由于只读了1K数据, 缓冲区中还剩1K数据, 在第二次调用 epoll_wait 时, epoll_wait 仍然会立刻返回并通知socket读事件就绪.直到缓冲区上所有的数据都被处理完, epoll_wait 才会立刻返回.支持阻塞读写和非阻塞读  简单点来说只要底层数据没有读完就epoll就会一直通知用户要读取数据LT 边缘触发Edge Triggered工作模式  如果我们在第1步将socket添加到epoll描述符的时候使用了EPOLLET标志, epoll进入ET工作模式 当epoll检测到socket上事件就绪时, 必须立刻处理.如上面的例子你妈喊你吃饭类似, 虽然只读了1K的数据, 缓冲区还剩1K的数据, 在第二次调用 epoll_wait 的时候, epoll_wait 不会再返回了.也就是说, ET模式下, 文件描述符上的事件就绪后, 只有一次处理机会.ET的性能比LT性能更高( epoll_wait 返回的次数少了很多). Nginx默认采用ET模式使用epoll.只支持非阻塞的读写 ET就是底层数据没有读完epoll也不会通知用户在去读取数据除非底层数据变化的时候(增多)才会在通知用户一次。  对于ET模式的效率是非常高的因为对于epoll在此模式下只有底层数据变化了才会通知用户去读数据但是我们不知道数据读完了所以就会倒逼着用户将本轮就绪的数据全部读取到上层(循环读取),所说一般的fd是阻塞式的但是在ET模式下的fd必须是非阻塞式的。 倒逼着用户将本轮就绪的数据全部读取到上层体现 不仅仅在通知机制上尽快让上层把数据都读走。也让T CP可以给对方发生提供了一个更大的窗口大小让对方更新出更大的滑动窗口让底层的数据发送效率更好其中TCP6位标志位中的PUH提示接收端应用程序立刻从TCP缓冲区把数据读走 。 select和poll其实也是工作在LT模式下. epoll既可以支持LT, 也可以支持ET。 四、epoll服务器  epollServer.hpp #pragma once#include iostream #include string #include cstring #include functional #include sys/epoll.h #include err.hpp #include log.hpp #include sock.hppnamespace epoll_ns {static const int defaultport 8888;static const int size 128;static const int defaultvalue -1;static const int defalultnum 64;using func_t std::functionstd::string(const std::string );class EpollServer{public:EpollServer(func_t f, uint16_t port defaultport, int num defalultnum): func_(f), _num(num), _revs(nullptr), _port(port), _listensock(defaultvalue), _epfd(defaultvalue){}void initServer(){_listensock Sock::Socket();Sock::Bind(_listensock, _port);Sock::Listen(_listensock);// 1 创建epoll模型_epfd epoll_create(size);if (_epfd 0){logMessage(FATAL, epoll create error: %s, strerror(errno));exit(EPOLL_CREATE_ERR);}// 2 添加listensocket到epoll中struct epoll_event ev;ev.events EPOLLIN;ev.data.fd _listensock;epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock, ev);// 3 申请就绪事情的空间_revs new struct epoll_event[_num];logMessage(NORMAL, init server success!);}void HandlerEvent(int readyNum){logMessage(DEBUG, HandlerEvent in);for (int i 0; i readyNum; i){uint32_t events _revs[i].events;int sock _revs[i].data.fd;if (sock _listensock (events EPOLLIN)){//_listensock读数据就绪获取新连接std::string clinetip;uint16_t clinetport;int fd Sock::Accept(sock, clinetip, clinetport);if (fd 0){logMessage(WARNING, accept error);continue;}// 获取fd成功放入到epoll中等struct epoll_event ev;ev.events EPOLLIN;ev.data.fd fd;epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, ev);}else if (events EPOLLIN){// 普通事情准备好了char buffer[1024];// 这里是有BUG的这里不能保证读取是完整信息这里先不解决int n recv(sock, buffer, sizeof(buffer) - 1, 0);if (n 0){buffer[n] 0;logMessage(DEBUG, client# %s, buffer);// 应答std::string respose func_(buffer);send(sock, respose.c_str(), respose.size(), 0);}else if (n 0){// 客户端退出了epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);close(sock);logMessage(NORMAL, client quit);}else{epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);close(sock);logMessage(ERROR, recv error, code: %d, errstring: %s, errno, strerror(errno));}}else{}}logMessage(DEBUG, HandlerEvent out);}void start(){int timeout -1;for (;;){int n epoll_wait(_epfd, _revs, _num, timeout);switch (n){case 0:logMessage(NORMAL, timeout...);case -1:logMessage(WARNING, epoll_wait failed,code:%d,errstring: %s, errno, strerror(errno));// 到这里事件都就绪了default:logMessage(NORMAL, have event ready);HandlerEvent(n);break;}}}~EpollServer(){if (_listensock ! defaultvalue)close(_listensock);if (_epfd ! defaultvalue)close(_epfd);if (_revs)delete[] _revs;}private:uint16_t _port;int _listensock;int _epfd;struct epoll_event *_revs;int _num;func_t func_;}; }在使用 telnet 命令连接到服务器后你可以通过几种方式来退出连接 发送 Telnet 命令序列 在 telnet 连接中你可以发送一些特殊的 Telnet 命令来结束连接。在连接中直接输入 Ctrl]然后输入 quit 或者 exit然后按回车键。 直接关闭 telnet 客户端 如果你不介意强制终止连接可以直接关闭或者终止 telnet 客户端。在大多数系统中你可以使用 CtrlC 或者 CtrlD 来中断当前运行的命令或程序。在这种情况下这将关闭 telnet 客户端并且终止连接。
http://www.hkea.cn/news/14542355/

相关文章:

  • angularjs 做团购网站什么做婚车网站最大
  • 网站制作报价黑河如何设计产品网站建设
  • 网站后台文件下载资阳网站制作
  • 网站备案关闭网站百度收录了我新网站的2篇文章了
  • 广州网站建设 粤icp网站开发的主题
  • 湘潭网站开发公司关于建设单位网站的方案
  • 公司网站制作服务做网站运营的股票
  • 视频网站主持人vue做社区网站
  • 茂名模板建站定制申请网站域名空间
  • 专业建设物流行业网站vps正常网站打不开
  • 广州网站关键字优化西安百度推广代理商
  • 海口快速建站模板柳州seo公司
  • 秦都区建设局网站通过服务推广网站
  • 搭网站要多少钱滁州新手跨境电商建站哪家好
  • 网站正在升级建设中代码中国室内设计联盟网官网
  • 英文在线购物网站建设启博学院的功能介绍
  • 可以做视频创收的网站wordpress 表情符号
  • 上海浦东哪里有做网站的公司5年的室内设计师收入
  • 江苏省建设厅网站挂证存疑名单合肥备案
  • 青岛网站设计企业帝国cms 网站例子
  • 做企业网站用哪个cmsgoogle英文网站
  • 重庆忠县网站建设公司哪家专业优化大师是什么意思
  • 专业网站建设排名做问卷的几个网站
  • wordpress读者墙不显示企业网站优化问题
  • 哈尔滨网站建设哪家好而且价格不贵wordpress两个域名访问
  • 网站建设打造学院建设招标网官方网站电脑版
  • 青海公司网站建设哪家快新媒体营销思维
  • 纯文字网站设计网站建设人员工作计划
  • 网站新闻怎么写网页设计师培训 网页设计师培训
  • 酒店网站建设描述个人网站的主题