传输层协议UDP
传输层
再谈端口号
端口号范围划分
- 0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的。
- 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的。
认识知名端口号(Well-Know Port Number)
- ssh 服务器, 使用 22 端口
- ftp 服务器, 使用 21 端口
- telnet 服务器, 使用 23 端口
- http 服务器, 使用 80 端口
- https 服务器, 使用 443 端口
执行下面的命令, 可以看到知名端口号
cat /etc/services
我们自己写一个程序使用端口号时, 要避开这些知名端口号.
两个问题
- 一个进程是否可以 bind 多个端口号?
一个进程可以绑定多个端口号。以下是详细的解释:
1. 技术实现原理:
Socket 独立性:每个网络连接通过套接字(Socket)管理,套接字由 IP 地址和端口号唯一标识。一个进程可以创建多个套接字,每个套接字独立绑定到不同的端口。
多路复用:通过多线程、多进程或异步 I/O(如
select
、epoll
)技术,进程可以同时监听多个端口的连接请求,处理并发通信。2. 实际应用场景:
多协议支持:例如 Web 服务器同时监听 HTTP(80 端口)和 HTTPS(443 端口)。
服务分离:同一进程提供不同功能的服务(如 API 接口和管理后台使用不同端口)。
负载均衡与代理:反向代理服务器(如 Nginx)可能监听多个端口,将流量分发到不同后端服务。
- 一个端口号是否可以被多个进程 bind?
1. 默认情况:端口独占性
在 默认配置 下,一个端口号(同一协议和 IP 地址)不允许被多个进程同时绑定。这是因为:
端口是网络通信的入口,操作系统需确保数据包能被正确路由到目标进程。
如果多个进程尝试绑定同一端口,操作系统会抛出
Address already in use
错误(如bind()
失败)。2. 允许绑定同一端口的条件
在以下场景中,多个进程可以绑定到同一端口:
(1) 不同协议
同一端口可以被 TCP 和 UDP 协议 的套接字同时绑定。
示例:DNS 服务器通常同时监听 TCP 和 UDP 的 53 端口。
(2) 不同 IP 地址
如果进程绑定到不同的 IP 地址(如多个网卡或多宿主主机),同一端口可被重复使用。
(3) 使用套接字选项
SO_REUSEADDR
或SO_REUSEPORT
SO_REUSEADDR
:
允许同一端口的套接字在特定条件下被重用(如原套接字已关闭或处于
TIME_WAIT
状态)。主要用于快速重启服务时避免端口占用冲突。
SO_REUSEPORT
(Linux 3.9+ 支持):
允许多个进程直接绑定到 相同的 IP 地址和端口。
操作系统内核会负责将连接请求负载均衡到不同进程。
应用场景:Nginx 多进程模型、高并发服务器优化。
UDP 协议
UDP 协议端格式
- 16 位 UDP 长度, 表示整个数据报(UDP 首部+UDP 数据)的最大长度;
- 如果校验和出错, 就会直接丢弃。
UDP 的特点
- 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接;
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP 协议层也不会给应用层返回任何错误信息;
- 面向数据报: 不能够灵活的控制读写数据的次数和数量;
面向数据报
- 如果发送端调用一次 sendto, 发送 100 个字节, 那么接收端也必须调用对应的一次 recvfrom, 接收 100 个字节; 而不能循环调用 10 次 recvfrom, 每次接收 10 个字节;
UDP 的缓冲区
- UDP 没有真正意义上的 发送缓冲区. 调用 sendto 会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作;
- UDP 具有接收缓冲区. 但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了, 再到达的 UDP 数据就会被丢弃;
UDP 的 socket 既能读, 也能写, 这个概念叫做 全双工 。
UDP 使用注意事项
基于 UDP 的应用层协议
- NFS: 网络文件系统
- TFTP: 简单文件传输协议
- DHCP: 动态主机配置协议
- BOOTP: 启动协议(用于无盘设备启动)
- DNS: 域名解析协议
本篇文章介绍了 传输层协议UDP 的相关内容,欢迎评论和交流!