这篇文章给大家带来传输层种UDP协议学习!!!
传输层是网络协议栈中重要的一层结构,前面所讲的应用层是调用下层协议来完成数据传输的
【传输层 – 百度百科】
传输层:主要负责向两个主机中进程之间的通信提供服务,负责数据能够从发送端传输接收端
传输层常用的二个协议分别是UDP(用户数据报协议)和 TCP(传输控制协议)
传输层提供逻辑连接的建立、传输层寻址、数据传输、传输连接释放、流量控制、拥塞控制、多路复用和解复用、崩溃恢复等服务
传输层中的大部分服务都是由TCP提供的,而UDP是无链接、不靠谱、面向数据报的,不用考虑超时重传、流量控制、拥塞控制等服务
端口号(Port)标识了一个主机上进行通信的不同的应用程序(进程)
端口号
源端口号:标识发送主机上进行网络通信的某个进程(具有唯一性)
目的端口号:标识接收主机上进行网络通信的某个进程(具有唯一性)
IP地址
IP地址是网络层IP协议中,用来标识网络中不同主机的地址(具有唯一性)
源IP地址:标定广域网(公网)中主机唯一性的地址(发送数据方的IP地址)
目的IP地址:标定广域网(公网)中主机唯一性的地址(接收数据方的IP地址)
通过IP地址和端口号可以标定网络中某台主机上的某个进程(具有唯一性)
在TCP/IP协议中,用 “源IP”,“源端口号”,“目的IP”, “目的端口号”,“协议号” 这样一个五元组来标识识别一个通信
下图解析
图中有三台主机,最左边这台是服务器,其余二台都是主机
客户端A在浏览器中启动了二个网页,它们IP地址一样,但是每个网页的端口号都不同,服务器可以根据传输层报文中的端口号对网页进行区分,从而构建不同的线程对其进行服务
客户端B只是单纯的起了一个网页,虽然它的端口号和客户端A的某个网页相同,但是它们的IP地址不同,说明它们不是相同的主机
端口号分为:知名端口号和动态端口号
[0, 1023]:知名端口号,HTTP, FTP, SSH等这些广为使用的应用层协议,他们的端口号都是固定的
[1024, 65535]:操作系统动态分配的端口号,客户端程序的端口号,就是由操作系统从这个范围分配的
注意:如果客户端程序绑定了知名端口号,可能会导致主机中的某些服务后续启动失败 或 启动当前的客户端失败等问题,因为端口号具有唯一性
有些服务器是非常常用的,为了使用方便,人们约定一些常用的服务器,都是用以下这些固定的端口号
- ssh服务器,使用22端口号
- ftp服务器,使用21端口号
- telnet服务器,使用23端口号
- http服务器,使用80端口号
- https服务器,使用443端口号
我们自己写一个程序使用端口号时,要避开这些知名端口号
一个进程可以绑定多个端口号,但是一个端口号只能被一个进程绑定(唯一性)
下面的命令, 可以查询知名端口号的服务
cat /etc/services
下图为UDP协议报文的组成结构
UDP报文的前64位(8字节)是UDP报文的首部,下面的数据是有效载荷,如果上层协议有数据则会放在这
16位UDP长度:表示整个UDP数据报(UDP首部 + UDP有效载荷(数据))的最大长度
16位UDP检验和:校验整个UDP的报文,包括UDP首部 和 UDP有效载荷在传输的过程中是否损坏,如果出错了则会直接丢弃数据包了(可选)
数据(有效载荷):应用层需要网络传输的数据(write、sendto、send接口等等)将会存放在这
UDP报文在代码中的逻辑结构
由于操作系统是C语言实现的,那么UDP报文就是一个结构化数据(结构体)
UDP报文的相关字段就是通过结构体进行保存的
我们所知的字段有源端口号、目的端口号、DUP数据报总长度和校验和
最后的数据(有效载荷),是应用层通过调用sendto、sendmsg系统调用来传输到下层UDP协议中的
UDP首部在内核中的表示方式,如下代码:
struct udphdr
{
__u16 source; // 源端口
__u16 dest; // 目标端口
__u16 len; // 数据包长度
__u16 check; // 校验和
};
sendto系统调用的调用链:
特点:
无连接:只要知道接收方的IP地址和端口号就能直接进行网络传输,不需要建立连接(三次握手)再通信
不可靠:没有确认应答机制,没有超时重传机制等等;如果因为网络故障发送失败,UDP协议也不会给应用层返回任何错误信息
面向数据报:不能够灵活的控制读写数据的次数和数量(不能将数据报拆分开来发送,只能一次性发送)
注意:不可靠是一个中性词,要看场景来选定协议,如果对比赛进行转播,那么肯定使用udp协议,因为丢包了只会卡住一会,如果使用tcp协议,丢包了,会直接掉线
面向数据报:
原理:应用层交给UDP协议多长的报文,UDP原样发送,既不会拆分,也不会合并
如果发送端调用一次sendto,发送200个字节,那么接收端也必须调用对应的一次recvfrom,接收200个字节;且不能循环调用10次recvfrom,每次接收20个字节
面向数据报不像面向字节流一样可以拆分和分段的发送,只能一次性发完全部数据
UDP缓冲区:
UDP其实没有真正意义上的发送缓冲区,因为它是不可靠的,直接调用sendto将网络传输的数据拷贝给内核,由内核将数据传给网络层协议进行后续的传输动作
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报文的顺序和发送UDP报文的顺序一致(数据报在网络传输中可能会由于路由选择的原因,走的比较慢或数据翻转等原因)
如果缓冲区满了,再到达的UDP数据就会被丢弃
UDP协议注意事项
UDP协议首部中的每个字段占16位的最大长度(2字节),也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部的全部字段)
如果使用UDP协议需要传输的数据超过64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装(这样就跟TCP协议面向字节流一样需要拼接合并了)
- NFS:网络文件系统
- TFTP:简单文件传输协议
- DHCP:动态主机配置协议
- BOOTP:启动协议(用于无盘设备启动)
- DNS:域名解析协议
- 也包括自己写的UDP程序时自定义的应用层协议