✧(≖ ◡ ≖✿
目录
传输层
端口号
六元组
端口号
端口号范围划分
端口号0-1023不是特定端口号吗?为什么可以sudo绑定?
进程与端口号的关系
UDP协议内核格式
UDP数据加工
UDP传输不是“不可靠”吗?为什么还有16位校验和呢?
为什么设计校验和?
UDP传输的特点
面向数据报
UDP的缓冲区
UDP 使用注意事项
基于 UDP 的应用层协议
传输层
负责数据能够从发送端传输到接收端。
端口号
每个端口号都代表特定主机下的一个程序。(IP代表一个主机)
六元组
当数据从发送端的应用层-传输层-网络层-数据链路层之后得到
端口号
端口号范围划分
【0,1023】:固定/知名端口号,HTTP, FTP, SSH等的固定的。 (像SSH:22 HTTP:80)
【1024,65535】:操作系统动态分配,客户端程序。(65536 == 2^16)
端口号0-1023不是特定端口号吗?为什么可以sudo绑定?
要回答“为什么是固定的,但sudo又能绑定”,核心在于区分两个概念:端口的使用规则(协议规定)和端口的绑定权限(操作系统规定)。
简单来说:0-1023的固定是“行业规范”,而sudo能绑定是“操作系统许可”。规范约束的是软件开发者,而许可约束的是系统用户。
进程与端口号的关系
怎样理解“一个进程可以绑定多个端口号,而应该端口号只能绑定一个进程”?
1.因为一个进程里可以开很多个Socket(套接字)。
进程是“容器”,Socket是它的“子工具”。
一个Web服务器(比如Nginx)启动后,它可以同时
bind(80)用于HTTP,同时bind(443)用于HTTPS,甚至再bind(8080)做个管理后台。这些端口号在操作系统内核的端口管理表里,虽然端口号不同,但它们对应的进程ID(PID)是同一个。
2.端口号的设置是程序级设计,目的在于标识系统下的唯一性程序。因此“只能绑定一个进程”,否则
如果有两个进程同时绑定80端口,内核就混乱了:“这个包到底该给谁?”
接下来在理解原理部分强调以下注意事项:
1. 构建立体化视角对于应用层、传输层、网络层。
2.基于“应用层”的根基思考网络的层状结构。
UDP协议内核格式
路径:linux-2.6.18\include\linux\udp.h
UDP数据加工
上部分就是位于传输层的UDP添加的报头。(下端是有效载荷)
16位UDP长度:表示自UDP首部+UDP数据的最大长度。
校验和:如果校验和出错,数据直接丢弃。
UDP传输不是“不可靠”吗?为什么还有16位校验和呢?
分析:UDP“不可靠”绝对没错,“不可靠”描述的是传输的“送达与否”。因此我们猜想“16位校验和”针对不是“信息送达”的可靠性相关。(这是分析问题的一种优秀的方式,你要学习)
答:UDP的“不可靠”与“校验和”不矛盾,反而巧合证明了它的设计哲学:“UDP校验和”是为了防止损坏的数据被滥用,而不是保证送达。
为什么设计校验和?
因为链路层(比如以太网)已经有CRC(循环冗余校验)了,UDP为什么还要自己再算一遍?
原因在于端到端的可靠性保障:
防止内存损坏:数据从应用层拷贝到内核缓冲区,再从内核缓冲区拷贝到网卡DMA(直接内存访问)区域,这中间可能因为硬件比特翻转(宇宙射线、电压不稳)导致某一位0变1。
防止中间设备篡改:虽然路由器不修改数据,但NAT(网络地址转换)设备可能重写IP头,旧的路由器可能存在Bug导致数据拷贝时出错。
防止“伪包”攻击:校验和可以验证这个包是不是发给我的(虽然不如TCP严格)。
UDP传输的特点
1.无链接:知道对端的IP和端口号就可以直接进行数据传输,无需建立链接。
2.不可靠:没有确认机制,没有重传机制。如果因为网络故障而没有到达,UDP协议层也不会返回任何错误信息。
3.面向数据报:不能够灵活的控制读写数据的次数和数量。(分包式传输)
面向数据报
应用层交给 UDP 多长的报文,UDP 原样发送,既不会拆分,也不会合并;
用 UDP 传输 100 个字节的数据:
・如果发送端调用一次 sendto, 发送 100 个字节,那么接收端也必须调用对应的一次 recvfrom, 接收 100 个字节;而不能循环调用 10 次 recvfrom, 每次接收 10 个字节;
UDP的缓冲区
UDP没有真正意义上的发送缓冲区。调用sendto会直接交给内核,将由内核传输数据给网络层协议进行后续的传输动作。
UDO具有接收缓冲区。但是这个缓冲区不能保证UDP报的顺序。(满则丢弃)
UDP的socket既能读,也能写。(具有全双工的性质:全双工(Full-Duplex)指的是通信双方可以同时进行发送和接收数据,互不干扰。)
UDP 使用注意事项
我们注意到,UDP 协议首部中有一个 16 位的最大长度。也就是说一个 UDP 能传输的数据最大长度是64K(包含 UDP 首部).
然而 64K 在当今的互联网环境下,是一个非常小的数字.
如果我们需要传输的数据超过 64K, 就需要在应用层手动的分包,多次发送,并在接收端手动拼装
基于 UDP 的应用层协议
・NFS: 网络文件系统
・TFTP: 简单文件传输协议
・DHCP: 动态主机配置协议
・BOOTP: 启动协议 (用于无盘设备启动)
・DNS: 域名解析协议
当然,也包括你自己写 UDP 程序时自定义的应用层协议;
感谢支持,长期连载
欢迎关注