一.誤區
因為TCP端口號是16位無符號整數, 最大65535, 所以一台服務器最多支持65536個TCP socket連接
這句話是錯誤的,實際上可監聽的最大端口號是65536。就像一台服務器安裝了一個nginx,他的默認端口是80,但可以改為65535,但支持的TCP連接可以是7萬個。
二.原理
系統通過一個四元組來唯一標識一條TCP連接,這個四元組的結構是{local ip, local port, remote ip, remote port}。
對於IPv4, 系統理論上最多可以管理2^(32+16+32+16), 2的96次方個連接。如果不僅僅考慮TCP, 則是一個五元組, 加上協議號(TCP, UDP或者其它)。
某個客戶端向同一個TCP端點(ip:port)發起主動連接, 那么每一條連接都必須使用不同的本地TCP端點, 如果客戶端只有一個IP則是使用不同的本地端口, 該端口的范圍在unix系統上的一個例子是32768到61000, 可以通過如下命令查看:
[root@linkops ~]# cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000
也就是說, 一個客戶端連接同一個服務器的同一個ip:port(比如進行壓力測試), 最多可以發起30000個左右的連接
TCP客戶端(TCP的主動發起者)可以在同一ip:port上向不同的服務器發起主動連接, 只需在bind之前對socket設置SO_REUSEADDR選項
系統支持的最大打開文件描述符數(包括socket連接):
[root@linkops ~]# cat /proc/sys/fs/file-max
580382
單個進程所能打開的最大文件描述符數:
[root@linkops ~]# ulimit -n
1024
三.端口號超過65535
下圖顯示的終端端口為78650 ,因為TCP PORT大小為16bit,所以不能超過65535
不過Windows會有一個問題,telnetwww.sina.com.cn 65616大家可以測試一下,這實際上是訪問 www.sina.com.cn 的80端口,為什么呢?
注:65616-65536=80
以下是引用片段:
main()
{
unsigned short int tcp_port=65616;
printf("%u",tcp_port);
}
有些軟件,比方說Windows的 Telnet ,可能用了32 bit的數據類型記錄port ,這樣port表面上看到是可以超過65535,但是tcp header明確定義了tcpport為16bit,那即便某些應用程序使用了32bit的數據類型,最終結果也是被強制轉換。
簡單的來說就是:
1.在應用程序里邊可以使用4字節或更多字節來儲存端口號
2.當調用了系統的tcp/ip通訊之后,系統底層強制將大於65536的端口轉換回正常范圍
3.並且在轉換過程中,不會返回任何錯誤信息,一切都悄然進行了,所以應用層的程序不會有任何特別反應,這一切都在系統底層悄然完成了
4.轉換的方式為:端口號 - 65536 = ?,問號處既是轉換結果
5.如果轉換后的端口還超過65535呢?那就繼續轉換,直到小於等於65535為止,所以telnet www.baidu.com 131152也是可以完美執行的,(65536 + 65536 + 80 = 131152)