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

在线免费看影视网站网站网站建设公

在线免费看影视网站,网站网站建设公,公司官网怎么做的,app官方安装免费下载From: http://blog.csdn.net/lsfa1234/article/details/6223635 高性能并发TCP网络服务IOCP框架修正VC2008版本 从Source Code里可发现#xff0c;此工程整合的epoll#xff0c;iocp及kqueue三种模型#xff0c;应该是非常有用的一个东东#xff08;如果ACE能够把它的那些…From: http://blog.csdn.net/lsfa1234/article/details/6223635 高性能并发TCP网络服务IOCP框架修正VC2008版本 从Source Code里可发现此工程整合的epolliocp及kqueue三种模型应该是非常有用的一个东东如果ACE能够把它的那些封装出来的每个东东都独立出来就太好了但由于时间关系未经测试。等测试OK再来Update具体状况。 点击浏览该文件 高并发TCP网络服务框架用Windows的IOCP、Linux的epoll、FreeBSD的kqueue写了一个支持高并发、多CPU、跨平台的TCP网络服务框架。测试下载netfrm.v2.rar解压缩得到netfrm.v2目录里面有netfrm.v2.vcproj和src目录。测试代码在src/main.cpp。 #include #include ./lance/ldebug.h #include ./lance/tcpsrv.hpp #include ./lance/systm.h class MyClient : public lance::net::Client { public: void OnConnect() { printf(OnConnect: fdx, ip%d, port%d//n, fd, ip, port); recv(data, 255); } public: void OnDisconnect() { printf(OnDisconnect: fdx, ip%d, port%d//n, fd, ip, port); } public: void OnRecv(int len) { data[len] 0x00; printf(OnRecv: fdx, data%s//n, fd, data); if (data[0] a) { printf(user exit command//n); close(); } recv(data, 255); } public: char data[256]; }; int main(char * args[]) { lance::net::TCPSrv srv; srv.ip 0; srv.port 1234; srv.ptr NULL; srv.backlogs 10; srv.threads 1; srv.scheds 0; srv.start(); while(true) { lance::systm::sleep(2000); } return 0; } 测试代码绑定本机所有IP地址在1234端口开启网络服务接收客户端发送的字符串并将这些字符串打印到控制台上。 Windows平台 在Windows XP SP2下用vs2003编译测试通过。 用vs2003打开netfrm.v2.vcproj然后编译、运行会弹出控制台窗口。在Windows开始菜单-运行-cmd启动Windows命令窗口输入telnet 127.0.0.1 1234回车连接到测试网络服务如果一切正常网络服务控制台窗口将显示连接信息可以在Windows命令窗口随便输入信息这时网络服务控制台窗口将打印输入的信息。如下图所示图1 输入字符a表示断开网络连接。 Linux平台 Linux在Red Hat Enterprise Linux 4下测试通过其他Linux平台需要Linux 2.6及以上支持epoll的内核。 首先转到src目录 $ cd src 编译 $ make –f Makefile.linux clean all 这时会在当前目录生成tcpsrv.0.1.bin的可执行文件 执行 $ ./ tcpsrv.0.1.bin 再打开一个命令行窗口 测试 $ telnet 127.0.0.1 1234 输入字符串并回车刚才执行tcpsrv.0.1.bin的窗口将打印连接和字符串信息。输入a开头的字符串将断开连接。 FreeBSD平台 FreeBSD在FreeBSD 6.2下测试通过其他BSD平台需要支持kqueue的内核。 首先转到src目录 $ cd src 编译 $ make –f Makefile.freebsd clean all 这时会在当前目录生成tcpsrv.0.1.bin的可执行文件 执行 $ ./ tcpsrv.0.1.bin 再打开一个命令行窗口 测试 $ telnet 127.0.0.1 1234 输入字符串并回车刚才执行tcpsrv.0.1.bin的窗口将打印连接和字符串信息。 输入a开头的字符串将断开连接。 使用目录结构 src |---lance |---tcpsrv.hpp 主要接口文件 |---iocptcpsrv.hpp Windows IOCP网络服务实现文件 |---eptcpsrv.hpp Linux epoll网络服务实现文件 |---kqtcpsrv.hpp FreeBSD kqueue网络服务实现文件 在某种平台下使用时src/lance/tcpsrv.hpp必须其他文件根据平台而定。 首先创建一个Client类这个类必须继承lance::net::Client重载事件通知方法。 // Client对象类当连接建立时自动创建当连接断开时自动销毁 class MyClient : public lance::net::Client { // 连接建立时被调动 public: void OnConnect() { printf(OnConnect: fdx, ip%d, port%d//n, fd, ip, port); // 通知调度系统接收数据 // 数据这时并没有真正接收当客户端有数据发送来时 // 调度器自动接收数据然后通过OnRecv通知数据接收完成 recv(data, 255); } // 连接断开时被调用 public: void OnDisconnect() { printf(OnDisconnect: fdx, ip%d, port%d//n, fd, ip, port); } // 当有数据被接收时调用接收的实际数据长度为len public: void OnRecv(int len) { data[len] 0x00; printf(OnRecv: fdx, data%s//n, fd, data); // 断开连接命令 if (data[0] a) { printf(user exit command//n); // 通知调度系统断开连接当调度系统处理完成后才真正断开连接 close(); } // 通知调度系统接收数据 // 数据这时并没有真正接收当客户端有数据发送来时 // 调度器自动接收数据然后通过OnRecv通知数据接收完成 recv(data, 255); } // 数据缓冲区 public: char data[256]; }; 然后创建一个lance::net::TCPSrv的实例这个实例负责调度网络服务。 具体代码参考src/main.cpplance::net::Client的OnConnect、OnRecv、OnDisconnect都由工作线程池处理所以里面可以进行IO操作而不会影响系统响应。 int main(char * args[]) { lance::net::TCPSrv srv; // 设置监听套接字绑定的IP // 0为绑定所有本机可用IP地址 srv.ip 0; // 监听端口 srv.port 1234; // 绑定的对象或资源指针 // MyClient里面可以通过srv-ptr获取这个指针 srv.ptr NULL; // 监听套接字连接队列长度 srv.backlogs 10; // 处理线程池线程数 srv.threads 1; // 调度器线程数通常是本机CPU数的2倍 // 0表示自动选择 srv.scheds 0; // 启动网络服务 srv.start(); // 循环保证进程不退出 while(true) { lance::systm::sleep(2000); } return 0; } Windows平台的预编译宏是LANCE_WIN32。 Linux平台的预编译宏是LANCE_LINUX。 FreeBSD平台的预编译宏是LANCE_FREEBSD。 Windows平台编译需要使用WIN32_LEAN_AND_MEAN和_WIN32_WINNT0x0500预编译宏来避免Winsock2和Windows头文件的冲突否则会产生大量类型重定义错误。  #define EPOLL_MAX_NFDS 10000 // max sockets queried by epoll. #define EPOLL_MAX_EVENTS 100 // max events queried by epoll. #define EPOLL_MAX_QUEUE 1024 // max events in cache queue. Linux平台有额外三个预编译宏参考src/lance/eptcpsrv.hpp FreeBSD平台有额外三个预编译宏参考src/lance/kqtcpsrv.hpp #define KQUEUE_MAX_NFDS 10000 // max sockets queried by kqueue. #define KQUEUE_MAX_EVENTS 100 // max events queried by kqueue. #define KQUEUE_MAX_QUEUE 1024 // max events in cache queue. Windows IOCP设计首先用户接口部分由两个类lance::net:TCPSrvlance::net::Client。 lance::net::TCPSrv管理监听套接字、事件调度和事件处理。 lance::net::Client管理连接套接字。 lance::net::TCPSrv由lance::net::Listener、lance::net::Scheduler、lance::net::Processor组成。他们之间的关系如下 图2 Listener管理监听套接字有单独的线程执行当有连接到来时创建一个Client的对象实例然后通过IOCP系统调用通知调度器有连接到来参考src/lance/iocptcpsrv.hpp template void Scheduler::push(T * clt) { ::PostQueuedCompletionStatus(iocp, 0, (ULONG_PTR)clt, NULL); } Scheduler实际并不做很多事情只是封装IOCP句柄Windows的IOCP功能很丰富包括管理事件队列和多CPU支持所以Scheduler只是一个IOCP的映射。 Processor管理线程池这些线程池是工作线程他们[FS:PAGE]轮询Scheduler的IOCP从中取出系统事件IOCP里面有三种事件一种是客户端连接事件一种是客户端数据事件最后一种是连接断开事件当有事件到来时会得到Client对象的指针cltClient的event包含了事件类型参考src/lance/iocptcpsrv.hpp template DWORD WINAPI Processor::run(LPVOID param) { Processor procor *(Processor *)param; Scheduler scheder *procor.scheder; HANDLE iocp scheder.iocp; DWORD ready; ULONG_PTR key; WSAOVERLAPPED * overlap; while (true) { ::GetQueuedCompletionStatus(iocp, ready, key, (LPOVERLAPPED *)overlap, INFINITE); T * clt (T *)key; switch(clt-event) { case T::EV_RECV: { if (0 ready) { clt-event T::EV_DISCONNECT; ::PostQueuedCompletionStatus(iocp, 0, (ULONG_PTR)clt, NULL); } else { clt-OnRecv(ready); } } break; case T::EV_CONNECT: { if (NULL ::CreateIoCompletionPort((HANDLE)clt-fd, iocp, (ULONG_PTR)clt, 0)) { ::closesocket(clt-fd); delete clt; } else { clt-OnConnect(); } } break; case T::EV_DISCONNECT: { clt-OnDisconnect(); ::closesocket(clt-fd); delete clt; } break; case T::EV_SEND: break; } } return 0; }  所以Client::OnConnect、Client::OnRecv、Client::OnDisconnect都在工作线程中进行这些处理过程中都可以有IO等耗时操作一个连接的阻塞不会影响其他连接的响应速度。 Client的其他方法Client::recv、Client::send和Client::close。 Client::recv是一个异步接收数据的方法这个方面只是告诉IOCP想要接收客户端的数据然后立即返回由IOCP去负责接收数据有数据收到时Processor的工作线程会收到Client::EV_RECV的消息Processor会调用Client::OnRecv进行通知。 Client::send是发送消息的函数这个函数是阻塞调用等待消息发送成功后才返回。 Client::close是主动断开客户端连接的方法这个方法不会直接调用closesocket(fd)而是调用shutdown(fd)shutdown(fd)会向Scheduler触发一个Client::EV_DISCONNECT的事件然后Processor调用Client::OnDisconnect通知连接断开执行完Client::OnDisconnect后由Processor调用closesocket(fd)真正断开连接这样设计一方面满足任何情况下OnDisconnect都被调用另一方面因为操作系统会重用已经关闭的套接字fd所以只有当OnDisconnect执行完毕后才真正调用closesocket让操作系统回收fd可以避免使用无效的套接字或者挪用其他连接的套接字。 Linux epoll和FreeBSD kqueue设计 Linux epoll和FreeBSD kqueue的机制几乎一样只有函数名字和个数不一样所以一起分析并且简写为Linux。因为Linux不像Windows一样会管理事件队列和多CPU支持所以Linux需要额外实现事件队列和多CPU支持。 Linux下用户接口跟Windows一样有lance::net::TCPSrv和lance::net::Client因为跨平台所以他们提供的接口功能和意义也一样参考Windows一节。 lance::net::TCPSrv管理连接套接字、事件队列、多CPU支持、事件调度和事件处理。 lance::net::TCPSrv由Listener、Scheduler、Processor、Queue组成。他们之间关系图如下图3 Listener管理监听套接字有连接到来时创建一个Client的实例clt初始化Client::event为Client::EV_CONNECT然后将clt放入调度器调度器为clt选择一个合适的epoll/kqueue进行绑定然后将clt放入事件队列Queue等待被Processor执行。 Scheduler管理epoll/kqueue为了支持多CPU一个Scheduler可能管理多个epoll/kqueue通过lance::net::TCPSrv::scheds进行设置当lance::net::TCPSrv::scheds大于1时Scheduler将创建scheds个线程每个线程管理一个epoll/kqueue。当Listener提交一个新的clt时Scheduler顺序选择一个epoll/kqueue进行绑定这是最简单的均等选择算法epoll/kqueue会检查绑定的clt的数据接收和连接断开事件如果有事件会把产生这个事件的clt放入事件队列Queue等待被Processor执行并且设置clt的套接字为休眠状态因为epoll/kqueue为状态触发如果事件在被Processor处理前不休眠会再次被触发这样Queue将被迅速填满。多CPU时依靠多个epoll/kqueue能有效利用这些CPU。参考eptcpsrv.hpp template void Scheduler::push(T * clt) { clt-epfd epers[epoff].epfd; epoff (epoff1 scheds)?0:(epoff1); queue.in(); while (queue.full()) { queue.fullWait(); } if (queue.empty()) { queue.emptyNotify(); } queue.push(clt); queue.out(); } Queue是有限缓冲队列有队列最大长度EPOLL_MAX_QUEUE/KQUEUE_MAX_QUEUE有限缓冲队列结构如下 图4 Queue采用monitor模式使用pthread_mutex_t lock保护临界区使用pthread_cond_t emptySignal做队列由空到不空的通知也就是唤醒消费者可以处理队列使用pthread_cond_t fullSignal做队列由满到不满的通知也就是唤醒生产者可以填充队列这里Scheduler是生产者Processor是消费者。 有时epoll/kqueue会一次产生多个事件如果先前队列为空那么需要通知Processor可以处理事件因为emptySignal.notify只能一次唤醒一个线程为了更加高效的处理事件应该使用emptySignal.broadcast唤醒所有工作线程。如果epoll/kqueue一次只产生了一个事件并且先前队列为空那么只需要使用emptySignal.notify唤醒一个工作线程而不应该使用emptySignal.broadcast唤醒工作线程因为只有一个事件所以只有一个线程会处理事件而其他线程会空转一次消耗资源。如果epoll/kqueue产生了事件但是队列不为空那么不需要唤醒工作线程的操作因为队列不为空的时候没有任何工作线程处于等待状态。代码参考eptcpsrv.hpp/Queue。 Processor跟Windows基本一样Processor从Queue取出事件然后根据clt-event事件类型调用响应的事件通知函数。 Client::recv也是一个请求接收数据的过程并不实际接收数据当有数据到来时Processor的工作线程负责接收数据然后调用Client::OnRecv通知响应的连接对象。 Cleint::send是一个同步阻塞函数等待数据真正发送完成后再返回。 Client::close跟Windows类似只是调用shutdown来触发断开消息然后处理流程跟Windows一致。
http://www.zqtcl.cn/news/159183/

相关文章:

  • 微信小程序怎拼做搬家网站东莞建网站公司
  • 网站推广昔年下拉博客推广链接制作软件
  • php 小企业网站 cmswordpress导航分类
  • 婚恋网站女孩子都是做美容免费空间最大的网盘
  • 建立网站要钱吗找人做网站需求怎么写
  • 网站建设精品课程电商运营主要负责什么
  • 中职网站建设与维护考试题wordpress商店会员管理
  • 物流网站开发策划做提升自己的网站
  • 网站开发交接做网站首页尺寸大小
  • 临沂建网站公司一个工厂做网站有用吗
  • 网站建设代码编译的问题及解决方案天元建设集团有限公司第六分公司
  • 做亚马逊网站费用深圳好蜘蛛网站建设公司
  • 做网站需要办什么手续html简单网页代码实例
  • 中文网页设计模板免费下载超级优化小说
  • 做网站的流程前端做什么网站建设与管理专业学什么
  • 用wordpress做购物网站西安建设工程网站
  • 响应式网站免费模板下载电商怎么做如何从零开始视频
  • 江西网站开发学校联系我们网站制作
  • 做网站首页图片素材营销网站制作要素
  • 云阳网站建设百度对 wordpress 排名
  • 做电商网站需要多少时间网站建设答辩ppt
  • 营销型网站的案例江苏seo网站排名优化
  • 企业网站 备案 网站名称凡科做视频网站
  • 湘潭建设公司网站杭州网站优化
  • 工信部备案网站网站空间服务商
  • 深圳市企业网站seo营销工具桂林百姓网
  • 网站建设所需材料wordpress nginx配置文件
  • 给企业做网站运营广州制作网站公司
  • 一个网站可以有几个关键词网页游戏制作过程
  • 网站可视化后台桥西区网站建设