摘自:4.18 TCP 和 UDP 可以使用同一个端口吗? | 小林coding (xiaolincoding.com)


TCP 和 UDP 可以同时绑定相同的端口吗?

答案:可以的

在数据链路层中,通过 MAC 地址来寻找局域网中的主机。在网络层中,通过 IP 地址来寻找网络中互连的主机或路由器。在传输层中,需要通过端口进行寻址,来识别同一计算机中同时通信的不同应用程序。

所以,传输层的「端口号」的作用,是为了区分同一个主机上不同应用程序的数据包。

传输层有两个传输协议分别是 TCP 和 UDP,在内核中是两个完全独立的软件模块。

当主机收到数据包后,可以在 IP 包头的「协议号」字段知道该数据包是 TCP/UDP,所以可以根据这个信息确定送给哪个模块(TCP/UDP)处理,送给 TCP/UDP 模块的报文根据「端口号」确定送给哪个应用程序处理。

img

因此, TCP/UDP 各自的端口号也相互独立,如 TCP 有一个 80 号端口,UDP 也可以有一个 80 号端口,二者并不冲突。

验证

简单写个 TCP 和 UDP 服务端的程序,它们都绑定同一个端口号 8888。

img

运行这两个程序后,通过 netstat 命令可以看到,TCP 和 UDP 是可以同时绑定同一个端口号的。

img


多个 TCP 服务进程可以绑定同一个端口吗?

如果两个 TCP 服务进程同时绑定的 IP 地址和端口都相同,那么执行 bind() 时候就会出错,错误是“Address already in use”

注意,如果 TCP 服务进程 A 绑定的地址是 0.0.0.0 和端口 8888,而如果 TCP 服务进程 B 绑定的地址是 192.168.1.100 地址(或者其他地址)和端口 8888,那么执行 bind() 时候也会出错。

这是因为 0.0.0.0 地址比较特殊,代表任意地址,意味着绑定了 0.0.0.0 地址,相当于把主机上的所有 IP 地址都绑定了。


客户端的端口可以重复使用吗?

客户端在执行 connect 函数的时候,会在内核里随机选择一个端口(32768 ~ 61000,共 28232 个),然后向服务端发起 SYN 报文,然后与服务端进行三次握手。

img

那么还可以继续使用该端口发起连接吗?

答案是可以的。

TCP 连接是由四元组(源IP地址,源端口,目的IP地址,目的端口)唯一确认的,那么只要四元组中其中一个元素发生了变化,那么就表示不同的 TCP 连接的。所以如果客户端已使用端口 64992 与服务端 A 建立了连接,那么客户端要与服务端 B 建立连接,还是可以使用端口 64992 的,因为内核是通过四元组信息来定位一个 TCP 连接的,并不会因为客户端的端口号相同,而导致连接冲突的问题。

比如下面这张图,有 2 个 TCP 连接,左边是客户端,右边是服务端,客户端使用了相同的端口 50004 与两个服务端建立了 TCP 连接。

img

仔细看,上面这两条 TCP 连接的四元组信息中的「目的 IP 地址」是不同的,一个是 180.101.49.12 ,另外一个是 180.101.49.11。

以上两个问题其实可以说是同一个问题,都是四元组相关的问题~