知识引入:
端口号:
当应用层获得一个传输过来的报文时,这时数据包需要知道,自己应该送往哪一个应用层的服务,这时就引入了“端口号”,通过区分同一台主机不同应用程序的端口号,来保证数据传输的可靠性!
而我们在之前的学习知道,ip地址是唯一的地址标识,那么我们借助ip地址和端口号是不是就能找到网络中唯一的一台主机?答案是肯定的,这也就是传输层协议存在的意义之一!
在TCP/IP协议中, 用 "源IP", "源端口号", "目的IP", "目的端口号", "协议号" 这样一个五元组来标识一个通信
如图我们通过源ip和源端口号,就知道信息是从哪来的,知道了目的ip和目的端口号就知道信息是去往哪里的。那么就能够实现网络中唯二的两个进程通过网络进行进程间通信了!!!
端口号划分:
- 0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的.
- 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.
查看网络连接状态命令:
// -ntpl n-带数字 t-TCP协议 p-服务名称 l-只查看listen服务
sudo netstat -ntpl
// ss命令也可以查网络服务
ss -nltp
常用选项:
- n 拒绝显示别名,能显示数字的全部转化成数字l 仅列出有在 Listen (监听) 的服務状态
- p 显示建立相关链接的程序名
- t (tcp)仅显示tcp相关选项
- u (udp)仅显示udp相关选项
- a (all)显示所有选项默认不显示LISTEN相关
UDP协议
UDP协议端格式
如图:UDP协议报文前8字节为UDP协议的报头,后面的即为有效载荷。
我们知道网络传输需要解决的四个问题:
- 报文如何将报头和有效载荷分离
- 有效载荷如何向上交付给对应应用层程序
- 报文内容是否完整
- 报文内容是否有误
联系UDP协议格式,我们发现以上四个问题对应:
- 解析固定报头长度来分开报头和有效载荷
- 再通过目的端口号将有效载荷交付给应用层服务
- 16位UDP长度对应着报文的长度(当长度不符时,直接丢包)
- 而16位UDP检验和检测是否在传输过程中出现0变成1、1变成0
通过UDP协议报头的设计,那么我们就解决了网络传输的4个问题,而在这里我们也能理解报头(协议)是一个结构化字段。
struct UdpHeader
{
uint32_t src_port:16;
uint32_t dest_port:16;
uint32_t length:16;
uint32_t check_sum:16;
}
又因为传输层是实现在操作系统中,也就是操作系统需要维护获得的UDP报文,需要对UDP报文实现“先描述再组织”
如图为:发送端如何形成UDP报文结构示意
- 首先应用层需要存在报头的结构化对象和管理报文信息的sk_buff结构化对象
- 当用户准备通过sendto进行发送时,通过bind函数将对应端口号写入进报头信息中,另外有效载荷写入sk_buff指向的缓冲区中,这时有tail执行有效载荷的尾,_data指向有效载荷的头部(_data-_tail即为有效载荷的长度)
- 传输层首先将_data向左移动8个字节,给UDP的报头放入,接着完善报头中的报文长度信息和check_num(可能是一种哈希映射)
- 最终就形成了一段UDP报文
因为系统中可能存在多份待发送的UDP报文,所以我们需要通过数据结构来管理这些报文。最终UDP协议就实现了!!!
当接收端接收到UDP报文时:
- 先分开报头和有效载荷(通过分离前8个字节数据),然后读取报头中的报文长度,就能找到有效载荷
- 通过对有效载荷进行哈希散列,判断前后的check_num是否相等,不相等就丢弃报文。
- 获取到报文后就可以通过对应端口,找到接受端的应用层服务
最终我们就完成了UDP通信!!!
UDP的特点
UDP传输的过程类似于寄信,为什么这么说呢,这和UDP的特点有关
- 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
- 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层 返回任何错误信息;
面向数据报: 不能够灵活的控制读写数据的次数和数量;(应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并; )
我们在传输报文时,只要知道对端的地址就可以进行传输,不需要事先通知对方才能够寄信。另外,当我们写信出去后我们就无法获得这封信的状态,除非他被对方收到,并且返回收到信息给你。最终,信的寄和读都是一次的行为,跟你信里面写了多少内容无关,是一个整体。
值得注意的是:UDP协议允许报文最长为16位,也就是64k的大小,当我们传输的内容大于64k时,我们就需要多次将数据分为64kb的报文,接着不断传输。