关于 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模型的原理:
引用
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();
addr.sin_addr.S_addr := htonl(INADDR_ANY);
bind( MainSock, @addr, sizeof(addr) );
listen( MainSock, ); while (not Terminated) do
begin
FD_ZERO( fd_read );
FD_SET( MainSock, fd_read );
timeout.tv_sec := ;
timeout.tv_usec := ;
if select( , @fd_read, nil, nil, @timeout ) > then //至少有1个等待Accept的connection
begin
if FD_ISSET( MainSock, fd_read ) then
begin
for i:= to fd_read.fd_count- 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;//临界区
};
可以看见,windows 下环境使用的临界区.
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 这个参数管理 ,就不说了.你懂的.
7,NotificationQueue 把 连接 放入队列.进行管理.
看完主要几个类的介绍,其它流程都应该懂大概了.
流程图:
由于图太长的关系多,
图片过宽,不能显示(请 在新标签中打开图片.谢谢.)
先看看 PooledThread 的流程吧
再看下TCPServer 主宰的流程
图片过宽,不能显示(请 在新标签中打开图片.谢谢.)
windows 下的select的确性能不太行,而linux 版本是用的epoll.
epoll相对select 要高效点.可参考:http://blog.csdn.net/legion8169/article/details/1637154
但poco tcpserver 中是有线程池操作的,所以说来效率不会太低.
先到这儿,还没有写完.
我们可以改变什么:
ThreadPool(int minCapacity = ,
int maxCapacity = ,
int idleTime = ,
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 中处理.
在中等程序中,增加 TCPSelect Manage进程, 来负责与多个 TcpServer 的进程通信.
即再增加一个管理者(中间键,或activemq之类),来加强并发能力,
或者直接使用linux 环境 ,即用了epoll 来实现高效性.
个人愚见,可能有些没写明白.还望高手指点.
谢谢.
关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.的更多相关文章
- Poco::TCPServer框架解析
Poco::TCPServer框架解析 POCO C++ Libraries提供一套 C++ 的类库用以开发基于网络的可移植的应用程序,功能涉及线程.文件.流,网络协议包括:HTTP.FTP.SMTP ...
- 实战web前端之:Bootstrap框架windows下安装与使用
Bootstrap是前端开发中比较受欢迎的框架,简洁且灵活.它基于HTML.CSS和JavaScript,HTML定义页面元素,CSS定义页面布局,而JavaScript负责页面元素的响应.Boots ...
- Scrapy框架Windows下安装
在windows下安装好Python3 后,安装Scrapy也有许多种方法,我这里采用pip 安装.前提您已经安装了pip 直接在cmd命令行中 pip install Scrapy building ...
- Windows下mnist数据集caffemodel分类模型训练及测试
1. MNIST数据集介绍 MNIST是一个手写数字数据库,样本收集的是美国中学生手写样本,比较符合实际情况,大体上样本是这样的: MNIST数据库有以下特性: 包含了60000个训练样本集和1000 ...
- 比较windows下的5种IO模型
看到一个很有意思的解释: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里. 这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socke ...
- scrapy爬虫框架windows下的安装问题
windows操作系统 python版本是3.6.0 通过Anaconda命令conda install scrapy安装scrapy,安装过程中没有问题. 然后在命令行输入命令准 ...
- 小白秒懂的Windows下搭建基于pytorch的深度学习环境
配置环境总体思路 1.依据python版本选择对应Anaconda版本: 2.依据显卡驱动版本选择对应的CUDA版本: 3.依据CUDA版本选择对应的cudnn和pytorch版本. 一.Anacon ...
- Linux下sed,awk,grep,cut,find学习笔记
awk awk是一种程序语言,对文档资料的处理具有很强的功能.awk擅长从格式化报文或从一个大的文本文件中抽取数据. awk的命令格式为: awk [-F filed-separator] “comm ...
- struts2框架之拦截器(参考第二天学习笔记)
拦截器 1. 什么是拦截器 1). 与JavaWeb中的Filter比较相似. 2). 拦截器只能拦截Action!!! 2. Struts中定义了很多拦截器,其中defaultStack中的拦截器会 ...
随机推荐
- 在CentOS 7 中 安装 VSFTP
在线安装:yum install -y vsftpd 使用yum 进行卸载:yum -y remove vsftpd 编辑配置:vi /etc/vsftpd/vsftpd.conf 查看FTP进程是否 ...
- a标签填充父容器
body>div>a{Join} div{ width:150px; height:35px; } a{ display:block; line-height:35px; height:3 ...
- 【阿里云配置端口开放】使用 iptables
要知道: 1.目前(16年-12-10)阿里云主机只要有服务开启,所有端口是默认开启的.这样很不好,安全做法是,需要开启外网端口时,由开发人员去配置. 2.想要开放端口,就需要使用iptables命令 ...
- java+eclipse+selenium环境搭建
这几天在学selenium,大头虾的我.安装环境还是遇到了挺多问题,赶紧来记录下.不然下次又...(参考虫师的<Selenium2 Java自动化测试实战>),就随便写写加深下自己的印象. ...
- Jade 模板引擎使用
在 Express 中调用 jade 模板引擎 jade 变量调用 if 判断 循环 Case 选择 在模板中调用其他语言 可重用的 jade 块 (Mixins) 模板包含 (Includes) 模 ...
- 让一个图片在div中居中(四种方法)
第一种方法: <div class="title"> <div class="flag"></div> <div cl ...
- tushare
tushare TuShare是一个免费.开源的python财经数据接口包.主要实现对股票等金融数据从数据采集.清洗加工 到 数据存储的过程,能够为金融分析人员提供快速.整洁.和多样的便于分析的数据, ...
- iOS-APP提交上架流程(新手必看!2016年3月1日最新版)
自己的经验总结,有错的话请留言,第一时间更改. 先大概说一下iOSAPP上架的几个步骤(详细步骤见下图): 创建证书请求文件 登录苹果开发者中心生成发布者证书(下载下来要双击一下) 设置APPID(要 ...
- HCP查询配置
1.配置命名空间Service里的Search功能为enable以及索引等相关配置 2.配置用户对该命名空间的查询为允许
- 从匿名方法到 Lambda 表达式的推演过程
Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. 以上是msdn官网对Lambda 表达式 ...