【Linux网络】UDP协议
目录
- 什么是UDP协议
- 端口号
- UDP协议格式
- UDP的特点
- 无连接
- 不可靠
- 面向数据包
- UDP的缓冲区
- 基于UDP的应用层协议
什么是UDP协议
UDP,全称是用户数据报协议,是一种非常基础的传输层协议,传输层通过端口号处理进程到进程之间的通信,网络通信的本质是不同主机中的不同进程之间的通信。
端口号
端口号是网络通信中用于标识特定应用程序或服务的16位数字(0-65535)。在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信。IP用于表示唯一一台主机,端口用于表示主机中唯一一个进程。
为什么不能用PID代替端口号呢?
(1)为了让进程控制模块和网络模块解耦。
(2)PID由系统分配,无法自己指定,这样就不能让客户端轻易的找到服务端。服务端结束重启的话,PID就又会重新分配了。
端口号范围划分:
0 - 1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的。
1024 - 65535:操作系统动态分配的端口号。客户端程序的端口号,就是由操作系统从这个范围分配的。
0 - 1023范围的端口号我们自己起的服务最好不要bind,普通用户也无法bind,root用户可以,但也最好不要,因为bind了会导致原本默认使用该端口号的服务起不来。
认识一些知名的端口号:
ssh服务器, 使用22端口
ftp服务器, 使用21端口
telnet服务器, 使用23端口
http服务器, 使用80端口
https服务器, 使用443
使用指令
cat /etc/services
可以查看知名端口号。
一个进程可以bind多个端口号,因为这不破坏端口号标定主机中的唯一一个进程的作用,而一个端口号通常不能被多个进程bind,因为这样端口号就不能标定主机中的唯一一个进程了。
UDP协议格式
UDP协议的格式相对简单,它的报头短小,且长度固定,这使得它可以很容易的分离报头。在8字节的报头中,有16位源端口和目的端口,这是传输层所必需的,不必多说。对于UDP长度,这里说的是整个报文的长度,因为报头的长度固定,所以实际上也可以很轻松的得出有效载荷的长度。UDP校验和可以用于校验UDP报文的是否错误,是否完整。
当传输层拿到UDP报文时,会和UDP长度进行比较,再用UDP校验和进行校验,没有问题了才会向上交付,UDP虽然不可靠,但是这不意味着它就可以将错误的报文向上传输。
UDP的特点
无连接
知道对端的IP和端口号就直接进行传输,不需要建立连接。
不可靠
没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。注意不可靠是因为自身机制导致的不可靠,能保证可靠性的UDP也是会保证的,像上面的校验,如果错误就是直接丢弃。
面向数据包
应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。发送方一次发送的报文接受方也必须一次接受,不能分次接受。
UDP的缓冲区
UDP没有真正意义上的发送缓冲区,但是系统有维护UDP发送队列,但我们想要调用sendto发送UDP报文时,系统会为我们开辟一份空间,写入报头(报头信息在系统中这样定义)
struct udphdr {__u16 source; // 源端口号,16位__u16 dest; // 目的端口号,16位 __u16 len; // UDP数据报长度,16位__u16 check; // 校验和,16位
};
然后写入数据,然后这样一个缓冲区又会被一个类似这样的结构体描述
struct sk_buff {char* start;char* end;char* pos;int type;// ……struct sk_buff* next;
};
这样的结构体串联起来,又被一个结构体描述,组成了发送队列。这样系统通过维护它就能管理UDP的收发了。
UDP有接收缓冲区,但是UDP接受的报文不能保证和发送时的顺序一致,这也是UDP不可靠的体现。如果UDP接收缓冲区满了,之后的数据就会被丢弃。
因为UDP的接受和发送不公用缓冲区,所以UDP的socket是全双工的。
因为UDP的报头UDP长度只有16位,这也意味着UDP的报文长度最大只有65535bit也就是64kb(包含报头)左右,所以要用UDP传大数据时就得分包了,但由于UDP不保证发送顺序的特性,所以如果应用层不处理,就没法用UDP发大数据了。
基于UDP的应用层协议
NFS: 网络文件系统
TFTP: 简单文件传输协议
DHCP: 动态主机配置协议
BOOTP: 启动协议(用于无盘设备启动)
DNS: 域名解析协议