併發TCP連接數可以有多少

網絡編程
在tcp應用中,server事先在某個固定端口監聽,client主動發起連接,經過三路握手後建立tcp連接。那麼對單機,其最大併發tcp連接數是多少?

如何標識一個TCP連接
在確定最大連接數之前,先來看看系統如何標識一個tcp連接。系統用一個4四元組來唯一標識一個TCP連接:{local ip, local port,remote ip,remote port}。

client最大tcp連接數
client每次發起tcp連接請求時,除非綁定端口,通常會讓系統選取一個空閒的本地端口(local port),該端口是獨佔的,不能和其他tcp連接共享。tcp端口的數據類型是unsigned short,因此本地端口個數最大隻有65536,端口0有特殊含義,不能使用,這樣可用端口最多隻有65535,所以在全部作爲client端的情況下,最大tcp連接數爲65535,這些連接可以連到不同的server ip。

server最大tcp連接數
server通常固定在某個本地端口上監聽,等待client的連接請求。不考慮地址重用(unix的SO_REUSEADDR選項)的情況下,即使server端有多個ip,本地監聽端口也是獨佔的,因此server端tcp連接4元組中只有remote ip(也就是client ip)和remote port(客戶端port)是可變的,因此最大tcp連接爲客戶端ip數×客戶端port數,對IPV4,不考慮ip地址分類等因素,最大tcp連接數約爲2的32次方(ip數)×2的16次方(port數),也就是server端單機最大tcp連接數約爲2的48次方。

 

那麼單臺服務器上的併發TCP連接數可以有多少

上面給出的是理論上的單機最大連接數,在實際環境中,受到機器資源、操作系統等的限制,特別是sever端,其最大併發tcp連接數遠不能達到理論上限。在unix/linux下限制連接數的主要因素是內存和允許的文件描述符個數(每個tcp連接都要佔用一定內存,每個socket就是一個文件描述符),另外1024以下的端口通常爲保留端口。在默認2.6內核配置下,經過試驗,每個socket佔用內存在15~20k之間。
影響一個socket佔用內存的參數包括:
rmem_max
wmem_max
tcp_rmem
tcp_wmem
tcp_mem
grep skbuff /proc/slabinfo
對server端,通過增加內存、修改最大文件描述符個數等參數,單機最大併發TCP連接數超過10萬 是沒問題的,國外 Urban Airship 公司在產品環境中已做到 50 萬併發 。在實際應用中,對大規模網絡應用,還需要考慮C10K 問題。

 

下面再詳解一下文件句柄限制和端口限制兩大常識

常識一:文件句柄限制

在linux下編寫網絡服務器程序的朋友肯定都知道每一個tcp連接都要佔一個文件描述符,一旦這個文件描述符使用完了,新的連接到來返回給我們的錯誤是“Socket/File:Can't open so many files”。

這時你需要明白操作系統對可以打開的最大文件數的限制。

進程限制

執行 ulimit -n 輸出 1024,說明對於一個進程而言最多隻能打開1024個文件,所以你要採用此默認配置最多也就可以併發上千個TCP連接。

臨時修改:ulimit -n 1000000,但是這種臨時修改只對當前登錄用戶目前的使用環境有效,系統重啓或用戶退出後就會失效。

重啓後失效的修改(不過我在CentOS 6.5下測試,重啓後未發現失效):編輯 /etc/security/limits.conf 文件, 修改後內容爲

* soft nofile 1000000

* hard nofile 1000000

永久修改:編輯/etc/rc.local,在其後添加如下內容

ulimit -SHn 1000000

全侷限制

執行 cat /proc/sys/fs/file-nr 輸出 9344 0 592026,分別爲:1.已經分配的文件句柄數,2.已經分配但沒有使用的文件句柄數,3.最大文件句柄數。但在kernel 2.6版本中第二項的值總爲0,這並不是一個錯誤,它實際上意味着已經分配的文件描述符無一浪費的都已經被使用了 。

我們可以把這個數值改大些,用 root 權限修改 /etc/sysctl.conf 文件:

fs.file-max = 1000000

net.ipv4.ip_conntrack_max = 1000000

net.ipv4.netfilter.ip_conntrack_max = 1000000

常識二:端口號範圍限制?

操作系統上端口號1024以下是系統保留的,從1024-65535是用戶使用的。由於每個TCP連接都要佔一個端口號,所以我們最多可以有60000多個併發連接。我想有這種錯誤思路朋友不在少數吧?(其中我過去就一直這麼認爲)

我們來分析一下吧

如何標識一個TCP連接:系統用一個4四元組來唯一標識一個TCP連接:{local ip, local port,remote ip,remote port}。好吧,我們拿出《UNIX網絡編程:卷一》第四章中對accept的講解來看看概念性的東西,第二個參數cliaddr代表了客戶端的ip地址和端口號。而我們作爲服務端實際只使用了bind時這一個端口,說明端口號65535並不是併發量的限制。

server最大tcp連接數:server通常固定在某個本地端口上監聽,等待client的連接請求。不考慮地址重用(unix的SO_REUSEADDR選項)的情況下,即使server端有多個ip,本地監聽端口也是獨佔的,因此server端tcp連接4元組中只有remote ip(也就是client ip)和remote port(客戶端port)是可變的,因此最大tcp連接爲客戶端ip數×客戶端port數,對IPV4,不考慮ip地址分類等因素,最大tcp連接數約爲2的32次方(ip數)×2的16次方(port數),也就是server端單機最大tcp連接數約爲2的48次方。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章