설명
내가 이 글을 쓰는 이유는 무엇입니까? Ah Er의 Dream Boat의
안타깝게도 코드가 너무 많아 번거로워 보여서 이해하기 쉽고 나중에 사용하기 편리하도록 순서도를 준비했습니다.
이 글의 내용은 윈도우 API 분석을 바탕으로 작성되었습니다.
이 글의 poco 버전은 1.4.6p4(2014-04-18)입니다. 현재 poco 버전은 1.6이지만 호출은 크게 바뀌지 않았습니다.
poco 다운로드 주소: http://pocoproject.org/releases/
이 문서에서는 TimeServer.cpp를 분석 진입점으로 사용합니다.
시작하기 전에 알아야 할 사항:
1, 인라인 인라인 함수: 다음을 참조할 수 있습니다.
http://blog.sina.com.cn/s/blog_90e888f50100zgo2.html
주로 실행 효율성을 높이기 위한 것입니다.
2, 오버로딩, 재작성, 클래스 멤버 함수 숨기기,
참고:
dazhong159의 <클래스 멤버 함수 오버로딩, 재작성, 오버라이딩의 차이점>
http://blog.csdn.net/dazhong159/article/details/7844369
3, 선택 모델의 원칙:
인용문
6가지 소켓 I/O 모델에 대한 유머러스한 설명
http://blog.csdn.net/normalnotebook/article/details/999840
내용:
for i:=0 to fd_read.fd_count-1 do //참고, fd_count
동기작동입니다.
첸 늙은이는 딸의 편지가 너무 보고 싶어해요. 10분마다 아래층으로 내려가서 딸이 보낸 편지가 있는지 확인하려고 할 정도로요~~~~
이 경우 '우편함을 확인하기 위해 아래층으로 내려갔다'고 다시 위층으로 올라가는 바람에 첸은 다른 일을 할 수 없을 정도로 지체됐다.
선택 모델은 Lao Chen의 상황과 매우 유사합니다. 계속 확인하고...데이터가 있으면...수신/보내기...
<span>..... MainSock :</span>=<span> socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); addr.sin_family :</span>=<span> AF_INET; addr.sin_port :</span>= htons(<span>5678</span><span>); addr.sin_addr.S_addr :</span>=<span> htonl(INADDR_ANY); bind( MainSock, @addr, </span><span>sizeof</span><span>(addr) ); listen( MainSock, </span><span>5</span><span> ); </span><span>while</span> (not Terminated) <span>do</span><span> begin FD_ZERO( fd_read ); FD_SET( MainSock, fd_read ); timeout.tv_sec :</span>= <span>0</span><span>; timeout.tv_usec :</span>= <span>500</span><span>; </span><span>if</span> <span>select</span>( <span>0</span>, @fd_read, nil, nil, @timeout ) > <span>0</span> then <span>//</span><span>至少有1个等待Accept的connection</span> <span> begin </span><span>if</span><span> FD_ISSET( MainSock, fd_read ) then begin </span><span>for</span> i:=<span>0</span> to fd_read.fd_count-<span>1</span> <span>do</span> <span>//</span><span>注意,fd_count <= 64,也就是说select只能同时管理最多64个连接</span> <span> begin len :</span>= <span>sizeof</span><span>(addr); ASock :</span>=<span> accept( MainSock, addr, len ); </span><span>if</span> ASock <><span> INVALID_SOCKET then ....</span><span>//</span><span>为ASock创建一个新的线程,在新的线程中再不停地select</span> <span> end; end; end; end; </span><span>//</span><span>while (not self.Terminated)</span> <span> shutdown( MainSock, SD_BOTH ); closesocket( MainSock ); end;<br></span></span>
따라서 셀렉트 모델은 일반적인 소규모 연결에만 사용할 수 있습니다....높은 동시성은 불가능합니다.
4,
생성자 초기화 순서의 이해
C++ 생성자는 다음 순서로 호출됩니다.
(1) 가상 기본 클래스의 생성자는 상속된 순서대로 생성됩니다.
(2) 가상이 아닌 기본 클래스의 생성자는 상속된 순서대로 생성됩니다.
(3) 멤버 개체의 생성자는 선언된 순서대로 호출됩니다.
(4) 클래스 자체의 생성자.
5, FastMutex 뮤텍스 변수에 대하여
boolNotificationQueue::empty() const
{ FastMutex::ScopedLock lock(_mutex);
return _nfQueue.empty();
}
empty()가 실행된 후 ~FastMutex::ScopedLock 소멸자를 호출하여 해제합니다.
창 아래에 사용되는 중요 섹션:
클래스 Foundation_API MutexImpl
{보호됨:
MutexImpl();
~MutexImpl();
void lockImpl();
bool tryLockImpl();
bool tryLockImpl(긴 밀리초);
void UnlockImpl();
private:
CRITICAL_SECTION _cs;//중요 섹션
};
6, 스레드 정보:
창문 밑에서 사용
_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);
스레드 연산을 실행합니다.
7, 이벤트 대기, 연결 요청 동기화가 사용됩니다
WaitForSingleObject(이것도 제가 가장 좋아하는 것입니다)
SetEvent(),ResetEvent()를 통해 재설정을 활성화합니다.
8, static_cast reinterpret_cast 사용법.
참고하세요:
http://www.cnblogs.com/bastard/archive/2011/12/14/2288117.html
http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html
코드와 마찬가지로:
무효* pThread;
reinterpret_cast
//reinterpret_cas 이 변환은 가장 "안전하지 않습니다". 이 변환을 사용하면 관련되지 않은 두 클래스 포인터 간의 변환이 가능합니다.
_threadId = static_cast//static_cast는 기본 데이터형 변환(char, int), 포인터 간 변환에 사용됩니다
9, 스마트(smart) 포인터 auto_ptr에 대하여
auto_ptr 간단히 말하면 생성된 리소스가 종료 시 해제될 수 있도록 보장합니다(예외 발생 여부에 관계 없음)
std::auto_ptr
<메모리>에서 직접 확인 가능
template
class auto_ptr
{ // 파괴를 보장하기 위해 객체 포인터를 래핑합니다
다음을 참고하세요.
http://blog.chinaunix.net/uid-9525959-id-2001803.html
의 단편:
如何避免使用auto_ptr的缺陷
auto_ptr并不是完美无缺的,它的确很方便,但也有缺陷,在使用时要注意避免。首先,不要将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做,否则可能会碰到不可预见的结果。
auto_ptr的另一个缺陷是将数组作为auto_ptr的参数:
auto_ptr
记住不管什么时候使用数组的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(<span>int</span> minCapacity = <span>2</span><span>, </span><span>int</span> maxCapacity = <span>16</span><span>, </span><span>int</span> idleTime = <span>60</span><span>, </span><span>int</span> stackSize =<span> POCO_THREAD_STACK_SIZE); </span><span>///</span><span> Creates a thread pool with minCapacity threads. </span><span>///</span><span> If required, up to maxCapacity threads are created </span><span>///</span><span> a NoThreadAvailableException exception is thrown. </span><span>///</span><span> If a thread is running idle for more than idleTime seconds, </span><span>///</span><span> and more than minCapacity threads are running, the thread </span><span>///</span><span> is killed. Threads are created with given stack size.</span>
增加线程池中线程数(费话!),来加快select 中处理.
个人愚见,可能有些没写明白.还望高手指点.
谢谢.
以上就介绍了关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。