TCP 端口监听队列原理
近期需要實現(xiàn)一個TCP線程池服務(wù),該服務(wù)需要能夠在同一個端口上實現(xiàn) TCP 常規(guī)服務(wù)、HTTP請求服務(wù)、SOAP WebService 服務(wù),為了測試 ACE 的線程池啟動后,如果所有線程都在忙,客戶端的連接是否還能夠建立,特實現(xiàn)了一個簡單的測試程序,如下:
ACE_TP_TEST#include?"stdafx.h"
//==================================================================================================
#define?DPS_DEBUG(?fmt?,??)?ACE_DEBUG((?LM_DEBUG?,?ACE_TEXT(?"%T?:?"?fmt?"\n"?)?,?__VA_ARGS__?))
#define?DPS_ERROR(?fmt?,??)?ACE_ERROR((?LM_ERROR?,?ACE_TEXT(?"%T?:?"?fmt?"\n"?)?,?__VA_ARGS__?))
//==================================================================================================
//????網(wǎng)絡(luò)流式套接字服務(wù)包裝類:自動將網(wǎng)絡(luò)輸入和關(guān)閉事件通知到連接管理類
struct?TPS_Servicer?:?public?ACE_Svc_Handler<?ACE_SOCK_STREAM?,?ACE_NULL_SYNCH?>
{
????virtual?int?handle_input(?ACE_HANDLE?Handler?=?ACE_INVALID_HANDLE?)
????{
????????DPS_DEBUG(?"Block?Handle?Input?&?Sleeping??"?,?0?);
????????while(?true?)?{?ACE_OS::sleep(?1000?);?}
????????return?0?;
????}
};
//==================================================================================================
//????網(wǎng)絡(luò)流式套接字服務(wù)監(jiān)聽包裝類:自動建立端口監(jiān)聽并接受連接同時將連接服務(wù)轉(zhuǎn)交給對應(yīng)的類
struct?TPS_Acceptor?:?public?ACE_Acceptor<?TPS_Servicer?,?ACE_SOCK_ACCEPTOR?>
{
????typedef?TPS_Servicer?Servicer_Handler?;
????typedef?ACE_Acceptor<?TPS_Servicer?,?ACE_SOCK_ACCEPTOR?>?Acceptor_Handler?;
????TPS_Acceptor(?ACE_INET_Addr?&?rAddress?)?:?Acceptor_Handler(?rAddress?)?{?}
????virtual?int?handle_input?(?ACE_HANDLE?hSock?)
????{
????????return?Acceptor_Handler::handle_input(?hSock?);
????}
};
//==================================================================================================
//????發(fā)動機(jī)的線程池包裝類(ACE_Reactor?ThreadPool)
struct?TPS_ServerReactor?:?public?ACE_Task_Base
{
????//????給定線程池中線程數(shù)目啟動反應(yīng)器線程池
????inline?TPS_ServerReactor(?long?nFlags?,?int?nThreads?=?16?)
????{
????????if(?activate(?THR_JOINABLE?|?nFlags?,?nThreads?)?==?-1?)
????????{
????????????DPS_ERROR(?"%T?:?Start?ThreadPool(%d)?failed"?,?nThreads?);
????????}
????}
????//????進(jìn)行反應(yīng)堆的事件處理
????virtual?int?svc()?{?return?ACE_Reactor::run_event_loop();?}????
};
//==============================================================================
//????程序處理的主函數(shù)
ACE_INT32?ACE_TMAIN(?ACE_INT32?nArg?,?ACE_TCHAR?*?lpArg[]?)
{
????//????設(shè)置多線程運行環(huán)境
????ACE_TP_Reactor?xtReactor;
????ACE_Reactor?xReactor(?&?xtReactor?);
????ACE_Reactor::instance(?&?xReactor?);
????ACE_ASSERT(?xReactor.initialized(?)?);
????//????建立網(wǎng)絡(luò)端口的監(jiān)聽
????ACE_INET_Addr?iNetAddr(?(ACE_UINT16)80?);
????TPS_Acceptor?xRemoteAcceptor(?iNetAddr?);
????//????啟動線程池開始服務(wù)
????TPS_ServerReactor?xProcessor(?THR_NEW_LWP?,?4?);????
????ACE_Thread_Manager::instance(?)->wait(?);
????return?xProcessor.wait(?);
}
啟動程序,該程序建立一個包含四個線程的線程池提供 TCP 服務(wù),在 80 端口上進(jìn)行監(jiān)聽,在客戶端使用 TELNET 來進(jìn)行測試,首先啟動四個客戶端,并且輸入一個字母,讓服務(wù)器的四個線程都進(jìn)行繁忙狀態(tài),然后在啟動一個客戶端,依然能夠進(jìn)行連接,想起 TCP 監(jiān)聽端口在有連接請求過來時是有一個隊列進(jìn)行緩沖的,該值默認(rèn)是 5,所以在啟動五個客戶端,這樣4個在繁忙,五個進(jìn)入了緩沖隊列,最后一個應(yīng)該連接不上了吧?結(jié)果發(fā)現(xiàn)啟動了幾十個客戶端全部都連上了,此時服務(wù)器的線程池都在“繁忙”中,主線程在等待線程池結(jié)束,那么是誰接受了客戶端的連接?郁悶不解中.......
查看 ACE 的源代碼,發(fā)現(xiàn)在建立 TCP 端口監(jiān)聽時,對緩沖隊列的大小設(shè)置是通過宏 ACE_DEFAULT_BACKLOG 來指定的,該宏在 Windows 上使用系統(tǒng)定義的 SOMAXCONN ,(在其他系統(tǒng)上使用默認(rèn)值 5) , 而 SOMAXCONN 的定義是 0x7fffffff , (當(dāng)然實際上不可能有這么多的連接到達(dá),即使有緩沖隊列也不可能容納的下,因為幾乎不可能有那么大的內(nèi)存來做緩沖)查閱 MSDN 說使用該值,系統(tǒng)將盡可能的緩沖所有的客戶端連接請求,就是說在 Windows 上,只要服務(wù)器系統(tǒng)能力允許,幾十服務(wù)器上的程序繁忙,客戶端的連接請求幾乎都能夠被系統(tǒng)緩存下來,客戶端不會發(fā)生連接失敗的情況;
最后在 TCP/IP 詳解一書中的 194 頁找到了相關(guān)的描述,在建立 TCP 的端口監(jiān)聽時可以指定一個連接的緩沖隊列,該隊列的長度上限在 Unix 和早期的 Windows 上默認(rèn)實現(xiàn)都是 5 個,在新版本的 Windows 中該隊列的上限系統(tǒng)不再做限制;
當(dāng)客戶端發(fā)起連接時,首先是 TCP 接受了該連接,然后應(yīng)用程序接受該連接,如果應(yīng)用程序忙沒有即時接受連接(即將該連接從 TCP 接受的連接隊列中移走)那么只有在隊列滿后 TCP 將不再接受客戶端的連接,所以此時服務(wù)器程序即使處于繁忙中,客戶端的連接因為 TCP 接受了,雖然服務(wù)器程序沒有接受該連接,但是客戶端的表現(xiàn)是連接已經(jīng)建立,但是發(fā)送任何內(nèi)容給服務(wù)器都沒有反映(因為服務(wù)器程序沒有接受該連接);
呵呵,原來如此......
轉(zhuǎn)載于:https://www.cnblogs.com/WonKerr/archive/2009/03/04/TCP_Listen_Queue.html
總結(jié)
以上是生活随笔為你收集整理的TCP 端口监听队列原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 录入学员的身份证后控件焦点转移时根据身份
- 下一篇: 记上海俱乐部活动