一、理論知識(文章來源:http://www.cnblogs.com/zwq194/archive/2012/12/14/2817673.html)
Socket 編程時,單機最多可以建立多少個 TCP 連接,受到操作系統的影響。
Windows 下單機的TCP連接數受多個參數影響:
最大TCP連接數
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
TcpNumConnections = 0x00fffffe (Default = 16,777,214)
以上注冊表信息配置單機的最大允許的TCP連接數,默認為 16M。這個數值看似很大,這個並不是限制最大連接數的唯一條件,還有其他條件會限制到TCP 連接的最大連接數。
最大動態端口數
TCP客戶端和服務器連接時,客戶端必須分配一個動態端口,默認情況下這個動態端口的分配范圍為 1024-5000 ,也就是說默認情況下,客戶端最多可以同時發起3977 個Socket 連接。我們可以修改如下注冊表來調整這個動態端口的范圍
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxUserPort = 5000 (Default = 5000, Max = 65534)
最大TCB 數量
系統為每個TCP 連接分配一個TCP 控制塊(TCP control block or TCB),這個控制塊用於緩存TCP連接的一些參數,每個TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就說,每個TCP連接會占用 1KB 的系統內存。
系統的最大TCB數量由如下注冊表設置決定
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)
非Server版本,MaxFreeTcbs 的默認值為1000 (64M 以上物理內存)
Server 版本,這個的默認值為 2000。
也就是說,默認情況下,Server 版本最多同時可以建立並保持2000個TCP 連接。
最大TCB Hash table 數量
TCB 是通過Hash table 來管理的,下面注冊表設置決定了這個Hash table 的大小
HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters]
MaxHashTableSize = 512 (Default = 512, Range = 64-65536)
這個值指明分配 pagepool 內存的數量,也就是說,如果MaxFreeTcbs = 1000 , 則 pagepool 的內存數量為 500KB
那么 MaxHashTableSize 應大於 500 才行。這個數量越大,則Hash table 的冗余度就越高,每次分配和查找 TCP 連接用時就越少。這個值必須是2的冪,且最大為65536.
參考: IBM WebSphere Voice Server 在windows server 2003 下的典型配置
MaxUserPort = 65534 (Decimal)
MaxHashTableSize = 65536 (Decimal)
MaxFreeTcbs = 16000 (Decimal)
二、個人總結
TCP/IP 協議規定的,只用了2個字節表示端口號。容易讓人誤解為1個server只允許連接65535個Client。
typedef struct _NETWORK_ADDRESS_IP
{
USHORT sin_port;//0~65535
ULONG in_addr;
UCHAR sin_zero[8];
} NETWORK_ADDRESS_IP, *PNETWORK_ADDRESS_IP;
(1)其實65535這個數字,只是決定了服務器端最多可以擁有65535個Bind的Socket。也就是說,最多可以開65535個服務器進程,但是你要知道這個能夠連接客戶端的數量沒有任何關系,Accept過來的Socket是不需要Bind任何IP地址的,也沒有端口占用這一說。作為Server端的Socket本身只負責監聽和接受連接操作。
(2)TCP協議里面是用[源IP+源Port+目的IP+目的 Port]來區別兩個不同連接,所以連入和連出是兩個不同的概念。連出Connect就不錯了,需要生成隨機端口,這個是有限的連入的話, 因SOCKET的分配受內存分頁限制,而連接受限制(WINDOWS)。
(3)所以,千萬不要誤以為1個server只允許連接65535個Client。記住,TCP連出受端口限制,連入僅受內存限制。
例如server,IP:192.168.16.254,Port:8009
Client1:IP:192.168.16.1,Port:2378
Client2:IP:192.168.16.2,Port:2378
Client1和Client2雖然Port相同,但是IP不同,所以是不同的連接。
(4)想讓1個server並發高效得連接幾萬個Client,需要使用IOCP“完成端口(Completion Port)”的技術。
詳情請參考文章:http://blog.csdn.net/libaineu2004/article/details/40087167
三、書籍推薦
《Linux多線程服務端編程:使用muduo C++網絡庫》,陳碩著。
請查閱“附錄D,關於TCP並發連接的幾個思考題與試驗”。