关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.

说明

为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010/09/10/123994.html

无奈代码太多,看起繁琐.所以 准备 以流程图简化,便于理解.也方便自己以后使用.

本文内容 是基于window api分析的.

本文的poco是1.4.6p4 (2014-04-18)版本的. 虽然现在poco版本是1.6 但调用改动不大.

poco下载地址:http://pocoproject.org/releases/

本文分析以 TimeServer.cpp 作为入口分析:

关于开始前的了解:

1,Inline 内联函数:可以参考:

http://blog.sina.com.cn/s/blog_90e888f50100zgo2.html

主要是提升执行效率.

2,类成员函数的 重载,重写,隐藏,

参考:

dazhong159 的<类成员函数的重载、重写、和覆盖区别>

http://blog.csdn.net/dazhong159/article/details/7844369

3,select模型的原理:

引用

很幽默的讲解六种Socket I/O模型

http://blog.csdn.net/normalnotebook/article/details/999840

的内容:

for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是说select只能同时管理最多64个连接

是同步操作.

老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信~~~~~
在这种情况下,"下楼检查信箱"然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作。
select模型和老陈的这种情况非常相似:周而复始地去检查......如果有数据......接收/发送.......

.....
 MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
 addr.sin_family := AF_INET;
 addr.sin_port := htons(5678);
 addr.sin_addr.S_addr := htonl(INADDR_ANY);
 bind( MainSock, @addr, sizeof(addr) );
 listen( MainSock, 5 );

 while (not Terminated) do
 begin
 FD_ZERO( fd_read );
 FD_SET( MainSock, fd_read );
 timeout.tv_sec := 0;
 timeout.tv_usec := 500;
 if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //至少有1个等待Accept的connection
 begin
 if FD_ISSET( MainSock, fd_read ) then
 begin
 for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是说select只能同时管理最多64个连接
 begin
 len := sizeof(addr);
 ASock := accept( MainSock, addr, len );
 if ASock <> INVALID_SOCKET then
 ....//为ASock创建一个新的线程,在新的线程中再不停地select
 end;
 end;
 end;
 end; //while (not self.Terminated)

 shutdown( MainSock, SD_BOTH );
 closesocket( MainSock );
 end;

所以,select模型,只能用于一般的小型连接....高并发是不行的.

4,

对构造函数初始化顺序的理解

C++构造函数按下列顺序被调用:
(1)任何虚拟基类的构造函数按照它们被继承的顺序构造;
(2)任何非虚拟基类的构造函数按照它们被继承的顺序构造;
(3)任何成员对象的构造函数按照它们声明的顺序调用;
(4)类自己的构造函数。

5,关于 FastMutex 互斥变量

bool NotificationQueue::empty() const
{
FastMutex::ScopedLock lock(_mutex);
return _nfQueue.empty();
}

在 empty() 执行完成后 调用 ~FastMutex::ScopedLock析构函数来释放.

window下是使用的临界区:

class Foundation_API MutexImpl
{
protected:
MutexImpl();
~MutexImpl();
void lockImpl();
bool tryLockImpl();
bool tryLockImpl(long milliseconds);
void unlockImpl();

private:
CRITICAL_SECTION _cs;//临界区
};

6,关于线程:

window下使用

_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);

执行线程的操作.

7,等待事件,连接请求的同步是使用的

WaitForSingleObject(这也是我的最爱)

通过SetEvent () ,ResetEvent() 来激活重置.

8,static_cast<>  reinterpret_cast<> dynamic_cast<> 的使用.

可参考:

http://www.cnblogs.com/bastard/archive/2011/12/14/2288117.html

http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html

像代码中:

void* pThread;

reinterpret_cast<ThreadImpl*>(pThread)->_pRunnableTarget->run();

//reinterpret_cas 这个转换是最“不安全”的,两个没有任何关系的类指针之间转换都可以用这个转换实现,举个例子

_threadId = static_cast<DWORD>(threadId);

//static_cast 用于基本的数据类型转换(char,int),及指针之间的转换

9,关于智能(灵巧)指针auto_ptr.

auto_ptr 简单点说,就是 保证创建的资源 在退出时能被free(无论有没有异常)

std::auto_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket()));

AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime);

可以直接 在<memory>中找到

template<class _Ty>
class auto_ptr
{ // wrap an object pointer to ensure destruction

可以参考:

More Effective C++中文版.pdf  7.4 Item M28:灵巧(smart)指针 章节(baidu 查到下载)

http://blog.chinaunix.net/uid-9525959-id-2001803.html

中的片段:

如何避免使用auto_ptr的缺陷

auto_ptr并不是完美无缺的,它的确很方便,但也有缺陷,在使用时要注意避免。首先,不要将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做,否则可能会碰到不可预见的结果。
    auto_ptr的另一个缺陷是将数组作为auto_ptr的参数:  
auto_ptr<char>  pstr (new char[12] ); //数组;为定义
 
    记住不管什么时候使用数组的new操作时,必须要用delete[]来摧毁数组。因为auto_ptr的析构函数只对非数组类型起作用。所以数组是不能被正确摧毁的话,程序的行为是不明确的。总之,auto_ptr控制一个由new分配的单对象指针,仅此而已。

不过C++ 11标准中解决了这问题:

unique_ptr

smart pointer with unique object ownership semantics

只能有一个主人的指针,可以用于STL容器

shared_ptr

smart pointer with shared object ownership semantics

可共享的指针

weak_ptr

weak reference to an object managed by std::shared_ptr

弱引用指针

auto_ptr

smart pointer with strict object ownership semantics

只能有一个主人的指针,不能用于STL容器

走远了,想深入(不要想多了-_- ),请baidu...

看完上面之些,发现是不是觉得 各种知识又巩固了.

所以还是要看开源代码,之前公司整死不用开源的...哎...

开始

代码中主要使用类的关系

图片过宽,不能显示(请 在新标签中打开图片.谢谢.)

主要的几个类:

1,TCPServer 主服务,负责 调用select 模型,来处理 连接消息的变化.

2,PooledThread 是线程池.当被激活时,调用 TCPServerDispatcher::run() 来处理收到包后的具体请求.而 TCPServerDispatcher::run()  中调用

    TimeServerConnection.run().  TimeServerConnection.run()通过子类隐藏 来实现 程序员 自定义 功能.  不得不说写POCO的大牛利害.

3,TCPServerDispatcher,派遣管理者(先这么叫吧). 接收消息变化,放入队列.管理 连接数.

当放入队列时,会激活  PooledThread 中的事件 .

PooledThread 又反过来 激活 TCPServerDispatcher::run() [姑且叫 有条件时相互激活吧 ]

4,TCPServerConnection.实现具体行为,通过继承由子类的 run() 来自定义实现 功能.

5,TCPServerConnectionFactory 负责创建和管理 TCPServerConnection.

6,TCPServerParams 这个参数管理 ,就不说了.你懂的.

看完主要几个类的介绍,其它流程都应该懂大概了.

流程图:

由于图太长的关系多,

图片过宽,不能显示(请 在新标签中打开图片.谢谢.)

先看看 PooledThread 的流程吧

再看下TCPServer 主宰的流程
图片过宽,不能显示(请 在新标签中打开图片.谢谢.)

先到这儿,还没有写完.

我们可以改变什么:

    ThreadPool(int minCapacity = 2,
        int maxCapacity = 16,
        int idleTime = 60,
        int stackSize = POCO_THREAD_STACK_SIZE);
        /// Creates a thread pool with minCapacity threads.
        /// If required, up to maxCapacity threads are created
        /// a NoThreadAvailableException exception is thrown.
        /// If a thread is running idle for more than idleTime seconds,
        /// and more than minCapacity threads are running, the thread
        /// is killed. Threads are created with given stack size.

增加线程池中线程数(费话!),来加快select 中处理.

个人愚见,可能有些没写明白.还望高手指点.

谢谢.

时间: 2024-12-18 00:44:00

关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.的相关文章

124第六章——在图形化界面下对磁盘进行常规管理 学习笔记

MBR:主引导扇区,在驱动器最前端的一段引导扇区,大小为512B(字节),由三部分组成,第一部分为主引导程序(boot loader),大小为446B,第二部分为分区表(partition table区),大小为64B,第三部分为magic number,大小为2B,固定为55AA.因为在分区表上记录一个主分区需要使用16B,所以整个硬盘的主分区和扩展分区最多只能是4个,不过在扩展分区上可以创建逻辑分区.Windows的系统文件必选安装在主分区上. 应用程序→系统工具→磁盘实用工具 124第六章

windows下 gvim8.0 编译器配置

最近由于各种原因,IDE从source insight换成了vim,参考了诸多博客的文章,折腾了好久折腾了个大概的样子,现在总结一下经验: 主要参考: 改造vim变成source insight Winxp下 gvim 编程环境搭建 VIM学习笔记 折叠 (Fold) 效果图: 1. 安装: 下载gvim8.0安装就可以了 刚装完是这个样子的: 2. 插件安装: 选用的插件如下表 插件名 作用 下载地址  安装方法(vimrc在后面统一配置) taglist 基于ctags的taglist ht

Windows 实现的 OSI 七层模型结构图

对网络编程感兴趣的朋友可能都听过 OSI 七层模型,下面一张便是在 Windows 下实现的整个协议的结构图. Windows 下的 OSI 七层模型的实现结构 +-------------------------------+ | Ws2_32.dll | +-------------------------------+ UserMode | | +-------------------------------+ | msafd.dll | +------------------------

windows下scrapy框架学习笔记—&#39;scrapy&#39; 不是内部或外部命令

最近几天在深入的学习scrapy框架,但是装完各种需要的基础包之后却发现scrapy命令在别的路径下都用不了,我一开始是把python安装在F:\Python路径下的,安装了scrapy后它默认都会安装在这个路径下,scrapy在路径F:\Python\Scripts路径下,我的scrapy命令只能在此路径下用,因此创建什么工程也都只能在此文件下. 想了一下它的工作原理:它在F:\Python\Scripts路径下,就会在Scripts文件下存在一个scrapy批处理文件,那么在DOS下想要命令

windows下游戏服务器端框架Firefly安装说明及demo运行

原地址:http://blog.csdn.net/wangqiuyun/article/details/11150503 本来公司一个网游服务器端选定了pomelo框架,后来出了个Firefly,为做一个对比,决定研究一下Firefly.看了一下Firefly,感觉头大,python的,本人python小白,只好慢慢折腾,一天下来总算装上了Firefly框架,并把他的那个开源网游<暗黑世界>服务器端跑了起来,特此记录共享! 其实关于这个框架的安装,他们的官网和BBS是有教程的只是太零散,并且面

windows下扩展yaf,并生成yaf框架文件

YAF中文文档:http://www.laruence.com/manual/index.html 1 YAF框架是用C开发的,属于PHP的扩展框架: 2 YAF的性能相对于源生PHP,性能只降低不到10%: 下面直接切入正题,如何在windows下扩展yaf并生成yaf框架文件(linux下就不赘述了,有很多资源讲解) 本机环境 PHP5.6.24 Apache 2.0 Handler YAF框架配置 要使用YAF首先要开启PHP的yaf扩展,由于集成环境不会自带所以我们得自己去下载: yaf

(转)windows下安装nodejs及框架express

转自:http://jingyan.baidu.com/article/456c463b60fb380a583144a9.html windows下安装nodejs及框架express nodejs从诞生至今一直被热捧,笔者最近也装了个node环境打算了解一下.安装步骤简单比较简单,所以在这里不会详细讲解每一步,只把安装过程中的问题解决了. 工具/原料 nodejs 框架express 方法/步骤 从node官网下载安装文件,官网地址:http://nodejs.org/   这个安装程序也很常

Windows下部署Appium教程(Android App自动化测试框架搭建)

摘要: 1,appium是开源的移动端自动化测试框架: 2,appium可以测试原生的.混合的.以及移动端的web项目: 3,appium可以测试ios.android.firefox os: 4,appium是跨平台的,可以用在osx,windows以及linux系统上: ----------------------------------------------appium的一些基本概念---------------------------------------------- appium

POCO库中文编程参考指南(10)如何使用TCPServer框架?

1 TCPServer 框架概述 POCO 库提供TCPServer框架,用以搭建自定义的 TCP 服务器.TCPServer维护一个连接队列.一个连接线程池.连接线程用于处理连接,连接线程只要一空闲就不断地从连接队列中取连接并进行处理.一旦连接线程从连接队列中取到一个连接,就会创建一个TCPServerConnection连接对象,并且调用该对象的start()方法,直到start()方法返回,这个连接对象就被删除了. 连接线程的数量是动态的,其取决于连接队列中排队的连接数.当然,你使用的时候