端口0:一般是用来表示所有端口,即1–65535。另外其他答主也提到1–1024是知名端口号,但那是很久以前数据,是该更新了。举几个大于1024的知名端口号:1614/1615:思科ISE用于AAA的端口号1812/1813:Radius服务器使用的端口号3306:数据库mysql使用的端口号3389:微软Windows远程桌面使用的端口号8080:一般的应用服务器使用的端口号,例如tomcat因此,还觉得知名端口号,范围是1–1024吗?在实际使用中,对于tcp,客户端使用的临时端口号,一般都是大于10000的。对于udp,客户端使用的临时端口号,可以从大于10000中选,也可以使用跟服务器一样的端口号。
TCP 连接数量最大不能超过 65535。这是因为 TCP 协议头中的端口号是 16 位的,因此最大只能表示 65535 个端口号。
在理解如何处理大量并发连接之前,我们需要了解为什么 TCP 连接数量最大不能超过 65535。在 TCP 协议中,每个连接都需要一个唯一的端口号和 IP 地址来标识。由于 TCP 协议头中的端口号只有 16 位,因此本地端口个数最大只有65536,端口0有特殊含义,不能使用,因此最多只能表示 65535 个端口号。因此,TCP 连接数量也被限制在 65535 个。
需要注意的是,这个限制是针对每个 IP 地址的。也就是说,每个 IP 地址最多只能有 65535 个 TCP 连接。如果有多个 IP 地址,则可以建立更多的连接。这也是为什么现代服务器通常都会有多个网卡和 IP 地址的原因之一。
65535是指可用的端口总数,并不代表服务器同时只能接受65535个并发连接。
举个例子:
我们做了一个网站,绑定的是TCP的80端口,结果是所有访问这个网站的用户都是通过服务器的80端口访问,而不是其他端口。可见端口是可以复用的。
即使Linux服务器只在80端口侦听服务, 也允许有10万、100万个用户连接服务器。Linux系统不会限制连接数至于服务器能不能承受住这么多的连接,取决于服务器的硬件配置、软件架构及优化。
一个进程绑定一个端口号”,这是显而易见的原则
当客户端要向服务器建立TCP连接时,会随机选择一个空闲端口,我们现在假设所有TCP都是长连接,那么当空闲端口被占用完后,自然无法创建更多的TCP连接,此时会报Cannot assign requested address的错误。我们都知道,端口号的取值范围是0~65535,既然端口号这么有限,服务器又是如何承受百万级甚至更高的并发量的?队列?缓存?多路复用?其实都没说到点子上
想象一下,一个nginx服务只占用一个80端口,难道它同时只能支撑一条TCP连接吗,显然不是的。那它又是如何区分到达同一端口的不同请求的呢?
TCP四元组
TCP四元组,简单来说,就是
<源IP地址,目标IP地址,源端口号,目标端口号>
在linux源码中,使用结构体sock_common表示
include/net/sock.h
struct sock_common {
/* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned
* address on 64bit arches : cf INET_MATCH()
*/
union {
__addrpair skc_addrpair;
struct {
__be32 skc_daddr; // 外部/目的IPV4地址
__be32 skc_rcv_saddr; // 本地绑定IPV4地址
};
};
// ...
/* skc_dport && skc_num must be grouped as well */
union {
__portpair skc_portpair; //
struct {
__be16 skc_dport; // inet_dport占位符
__u16 skc_num; // inet_num占位符
};
};
// ...
}
真实的sock_common比上面展示的要复杂的多,但要理解四元组,看这些部分就足够了
在连接建立之初,服务器会根据四元组信息为每条不同的TCP连接建立socket,并保存在内存中。当客户端向服务端发送数据包时,会将四元组信息携带在ip头信息当中,服务端收到数据包之后,解析四元组信息,在内存中查找对应的socket。服务器使用不同的socket和不同的客户端进行通信,也就是说,只要四元组中有任意元素不相同,服务器就能判断出这是一个不同的连接,会使用不同的socket与其通信,而socket和端口并不是一一绑定的关系,只要资源充足,一个服务器进程可以创建出几百万条socket连接。
我们现在知道,服务器可以复用同一端口创建多条TCP连接,那另一方面,是否意味着客户端一条连接就需要占用一个端口呢?
对于客户端来说,源IP地址一定是确定的,那么如果要请求特定目标IP的特定端口,为了保证四元组中至少有一个元素不同,那么确实需要绑定多个端口才能并发创建多个连接。但这并不意味着一个客户端端口只能承载一个连接,只要目标IP和目标端口任意一个发生变化,就可以在同一端口下继续创建多条连接。同一台客户端机器有多个IP的话,也可以复用同一个端口;包括TCP和UDP也可以复用同一个端口。
假设有一台服务器,上面运行着Nginx服务,占用了80端口,那么它理论上的最大并发承载量是多少呢,根据四元组规则, 他的理论承载能力为:
2^32 * 2^16
其中232表示IPV4理论个数,216表示端口最大数量
当然没有哪台服务器可以承受几百万亿的并发量,究其原因,是因为每创建一个socket连接,都需要占用一定的内存。而且对于linux来说,创建连接实际上就是打开一个新文件,而为了防止打开过多文件导致系统崩溃,linux在系统层面和用户层面均设置了最大文件打开数。 作者:子非鱼nofish https://www.bilibili.com/read/cv17459503 出处:bilibili