UDP和TCP可以使用同一个端口吗?

本文详细探讨了TCP和UDP是否可以同时绑定相同的端口,多个TCP服务进程是否能绑定同一个端口,客户端端口的复用情况,以及客户端TCP连接TIME_WAIT状态过多时的影响和解决方案。通过实例和内核机制解释了端口绑定规则及TCP/IP协议的工作原理,解答了相关面试问题。
摘要由CSDN通过智能技术生成

之前有读者在面试的时候,被问到:TCP 和 UDP 可以同时监听相同的端口吗?

1ec58894f423b9d1c8a8f547cb313187.jpeg

关于端口的知识点,还是挺多可以讲的,比如还可以牵扯到这几个问题:

  • 多个 TCP 服务进程可以同时绑定同一个端口吗?
  • 客户端的端口可以重复使用吗?
  • 客户端 TCP 连接 TIME_WAIT 状态过多,会导致端口资源耗尽而无法建立新的连接吗?

所以,这次就跟大家盘一盘这些问题。

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

其实我感觉这个问题「TCP 和 UDP 可以同时监听相同的端口吗?」表述有问题,这个问题应该表述成「TCP 和 UDP 可以同时绑定相同的端口吗?

因为「监听」这个动作是在 TCP 服务端网络编程中才具有的,而 UDP 服务端网络编程中是没有「监听」这个动作的。

TCP 和 UDP 服务端网络相似的一个地方,就是会调用 bind 绑定端口。

给大家贴一下  TCP 和 UDP 网络编程的区别就知道了。

TCP 网络编程如下,服务端执行 listen() 系统调用就是监听端口的动作。

0eaaf1b12b0731944ae5d4128bddbf1d.jpeg

TCP 网络编程

UDP 网络编程如下,服务端是没有监听这个动作的,只有执行  bind()  系统调用来绑定端口的动作。

d47cbde04a94c2fd64711a84860c39c1.jpegUDP 网络编程

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

答案:可以的

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

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

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

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

7b775218b94e43b948a88aa3aef4be8a.jpeg

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

验证结果

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

2114a0d4b9335eaf7a3af86aba26144e.jpeg

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

5a95964a69c8560305218f108d92e689.jpeg

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

还是以前面的 TCP 服务端程序作为例子,启动两个同时绑定同一个端口的 TCP 服务进程。

运行第一个  TCP 服务进程之后,netstat 命令可以查看,8888 端口已经被一个 TCP 服务进程绑定并监听了,如下图:

facb3fa251db3c736d015b5f24afc667.jpeg

接着,运行第二个 TCP 服务进程的时候,就报错了“Address already in use”,如下图:

0dd182727e6b4a412d3fc8a8bedb9117.jpeg

我上面的测试案例是两个 TCP 服务进程同时绑定地址和端口是:0.0.0.0 地址

可以使用Keepalived结合LVS(Linux Virtual Server)来实现负载均衡和高可用。在配置时,可以在keepalived的配置文件中指定多个RealServer,并在LVS的配置文件中指定一个VirtualServer。这样,多个RealServer就可以共同提供服务。 要监听同一个TCP/UDP端口,可以在LVS配置文件中指定VirtualServer的IP地址和端口号,然后将这个VirtualServer绑定到多个RealServer上。这样,当客户端请求这个端口时,LVS就会将请求转发到多个RealServer上,从而实现负载均衡和高可用。 下面是一个简单的例子,展示了如何使用Keepalived和LVS来监听同一个TCP端口: 1. 在keepalived的配置文件中,定义Virtual IP地址(VIP)和Virtual Router ID(VRID): ``` vrrp_script chk_http_port { script "/etc/keepalived/check_http" interval 2 } vrrp_instance VI_1 { interface eth0 state MASTER virtual_router_id 51 priority 101 virtual_ipaddress { 192.168.1.100/24 dev eth0 } track_script { chk_http_port } } ``` 在上面的配置中,我们定义了一个Virtual IP地址为192.168.1.100,并指定了Virtual Router ID为51。我们还定义了一个名为chk_http_port的脚本,该脚本将会在后面的LVS配置中使用,用来检查RealServer的状态。 2. 在LVS的配置文件中,指定VirtualServer的IP地址和端口号,并将其绑定到多个RealServer上: ``` virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wrr lb_kind NAT protocol TCP real_server 192.168.1.10 80 { weight 1 TCP_CHECK { connect_timeout 3 connect_port 80 } } real_server 192.168.1.20 80 { weight 1 TCP_CHECK { connect_timeout 3 connect_port 80 } } } ``` 在上面的配置中,我们定义了一个VirtualServer,其IP地址为192.168.1.100,端口号为80。我们将这个VirtualServer绑定到两个RealServer上,分别为192.168.1.10和192.168.1.20。我们还指定了TCP协议,并使用了NAT模式的负载均衡算法。 通过以上配置,当客户端请求192.168.1.100:80时,LVS会将请求转发到多个RealServer上,从而实现负载均衡和高可用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值