Home > Article > Backend Development > About Poco::TCPServer framework (select model is used under windows) study notes., pocotcpserver_PHP tutorial
Why am I writing this article? I have read Ah Er’s Dream Boat’s ab570f199d08d129f6da4f7f248ad914 http://www.cppblog.com/richbirdandy/archive/2010/09/10/123994 .html
Unfortunately, there are too many codes and it looks cumbersome. So I prepared a flow chart to simplify it for easy understanding and convenience for future use.
The content of this article is based on window api analysis.
The poco of this article is version 1.4.6p4 (2014-04-18). Although the poco version is now 1.6, the call has not changed much.
poco download address: http://pocoproject.org/releases/
This article uses TimeServer.cpp as the entry point for analysis:
1, Inline inline function: You can refer to:
http://blog.sina.com.cn/s/blog_90e888f50100zgo2.html
Mainly to improve execution efficiency.
2, Overloading, rewriting, hiding of class member functions,
Reference:
dazhong159's 49786b7d19a3ec00e56f6cbf6d1d215a
http://blog.csdn.net/dazhong159/article/details/7844369
Extensively used, rewritten, and hidden in the code.
3, Principle of select model:
Quote
A humorous explanation of the six Socket I/O models
http://blog.csdn.net/normalnotebook/article/details/999840
Contents of:
for i:=0 to fd_read.fd_count-1 do //Note, fd_count
It is a synchronous operation.
Old Chen really wants to see his daughter’s letter. So much so that he goes downstairs to check the mailbox every 10 minutes to see if there is a letter from his daughter~~~~~
In this case, "going downstairs to check the mailbox" and then going back upstairs took up so much time that Chen couldn't do other work.
The select model is very similar to Lao Chen’s situation: check over and over again...if there is data...receive/send...
<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 /><br /></span>
So, the select model can only be used for general small connections....high concurrency is not possible.
4,
C constructors are called in the following order:
(1) The constructors of any virtual base class are constructed in the order in which they are inherited;
(2) The constructors of any non-virtual base class are constructed in the order in which they are inherited;
(3) The constructors of any member objects are called in the order in which they are declared;
(4) The class's own constructor.
5, About FastMutex mutex variables
bool NotificationQueue::empty() const
{
FastMutex::ScopedLock lock(_mutex);
return _nfQueue.empty();
}
After empty() is executed, call the ~FastMutex::ScopedLock destructor to release it.
The critical section used under window:
class Foundation_API MutexImpl
{
protected:
MutexImpl();
~MutexImpl();
void lockImpl();
bool tryLockImpl();
bool tryLockImpl(long milliseconds);
void unlockImpl();
private:
CRITICAL_SECTION _cs;//Critical section
};
You can see the critical section used in the Windows environment.
6, About threads:
Use under window
_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);
Execute thread operations.
7, waiting for events, synchronization of connection requests is used
WaitForSingleObject(This is also my favorite)
Activate reset through SetEvent (),ResetEvent().
8, static_casta8093152e673feb7aba1828c43532094 reinterpret_casta8093152e673feb7aba1828c43532094 dynamic_casta8093152e673feb7aba1828c43532094 usage.
Please refer to:
http://www.cnblogs.com/bastard/archive/2011/12/14/2288117.html
http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html
Like in code:
void* pThread;
reinterpret_cast147a4b1a9ac393e5423001daaf52d3c1(pThread)->_pRunnableTarget->run();
//reinterpret_cas This conversion is the most "unsafe". Conversion between two unrelated class pointers can be achieved using this conversion. For example
_threadId = static_cast4737c366a7480835d11977311551913f(threadId);
//static_cast is used for basic data type conversion (char, int), and conversion between pointers
9, About the smart (smart) pointer auto_ptr.
auto_ptr To put it simply, it ensures that the created resources can be freed when exiting (regardless of whether there is an exception or not)
std::auto_ptr432460fadd740d5c208985304243c6fe pConnection(_pConnectionFactory->createConnection(pCNf->socket()));
AutoPtr48f31c4cc7c901a65b076f4d942e8d27 pNf = _queue.waitDequeueNotification(idleTime);
can be found directly in e57bfaee39f2b4342f13553bc6334c96
template3ed4dd42ab208b5833c94137c0f66641
class auto_ptr
{ // wrap an object pointer to ensure destruction
You can refer to:
More Effective C Chinese version.pdf 7.4 Item M28: Smart Pointer Chapter (find and download on baidu)
http://blog.chinaunix.net/uid-9525959-id-2001803.html
Fragment from:
How to avoid the pitfalls of using auto_ptr
Auto_ptr is not perfect. It is indeed very convenient, but it also has pitfalls. You should pay attention to avoid it when using it. First of all, do not use auto_ptr objects as elements of STL containers. The C standard explicitly prohibits this, otherwise unforeseen results may be encountered.
Another flaw of auto_ptr is to use an array as a parameter of auto_ptr:
auto_ptr424b5ca5994d08464738b3617afd1719 pstr (new char[12] ); //Array; is defined
Remember that whenever you use the new operation of an array, you must use delete[] to destroy the array. Because the destructor of auto_ptr only works on non-array types. So if the array cannot be destroyed correctly, the behavior of the program is unclear. In short, auto_ptr controls a single object pointer allocated by new and nothing more.
However, this problem is solved in the C 11 standard:
unique_ptr
smart pointer with unique object ownership semantics
There can only be one owner pointer, which can be used for STL containers
shared_ptr
smart pointer with shared object ownership semantics
Sharable pointers
weak_ptr
weak reference to an object managed by std::shared_ptr
Weak reference pointer
auto_ptr
smart pointer with strict object ownership semantics
There can only be one owner pointer and cannot be used in STL containers
I have gone far and want to go deeper (don’t think too much -_-), please baidu...
After reading the above, I found out that all kinds of knowledge have been consolidated.
So we still have to look at open source code. In the past, the company didn’t use open source at all... Hey...
The picture is too wide and cannot be displayed (please open the picture in a new tab. Thank you.)
1, TCPServer main service, responsible for calling the select model to handle changes in connection messages.
2. PooledThread is a thread pool. When activated, TCPServerDispatcher::run() is called to handle the specific request after receiving the package. And TCPServerDispatcher::run() is called
TimeServerConnection.run(). TimeServerConnection.run() is hidden by subclasses to implement programmer-defined functions. I have to say the advantages and disadvantages of writing POCO.
3, TCPServerDispatcher, dispatch manager (let’s call it that for now). Receives message changes, puts them into the queue, and manages the number of connections.
When placed in the queue, the event in PooledThread will be activated.
PooledThread in turn activates TCPServerDispatcher::run() [let’s call it mutual activation when conditions permit]
4, TCPServerConnection. To implement specific behaviors, customize the implementation function by inheriting the run() of the subclass.
5,TCPServerConnectionFactory is responsible for creating and managing TCPServerConnection.
6, TCPServerParams parameter management, I won’t talk about it. You know.
7,NotificationQueue puts the connection into the queue for management.
After reading the introduction of the main categories, you should have a general understanding of other processes.
Because the picture is too long, there are many reasons,
The picture is too wide and cannot be displayed (please open the picture in a new tab. Thank you.)
The performance of select under windows is indeed not very good, and the linux version uses epoll.
epoll is more efficient than select. Please refer to: http://blog.csdn.net/legion8169/article/details/1637154
但poco 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 中处理.
在中等程序中,增加 TCPSelect Manage进程, 来负责与多个 TcpServer 的进程通信.
即再增加一个管理者(中间键,或activemq之类),来加强并发能力,
或者直接使用linux 环境 ,即用了epoll 来实现高效性.
个人愚见,可能有些没写明白.还望高手指点.
谢谢.