传输层——UDP协议
文章目录
- 端口号
- 端口号范围划分
- UDP协议
- UDP协议端格式
- UDP的缓冲区
- UDP传输最大长度
负责数据能够从发送端传输接收端
前面提及到应用层协议HTTP,其目的是为了保护数据的安全,而传输层则是为了
保证数据能够可靠地传送到目标地址;
端口号
端口号(Port)标识了一个主机上进行通信的不同的应用程序
在主机上往往存在着不同的多种服务,从网络中获取的数据在进行向上交付时,在传输层就会提取出该数据对应的目的端口号,进而确定该数据应该交付给当前主机上的哪一个服务进程
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信
可以通过netstat -n命令来查看五元组的信息
端口号范围划分
- 0 - 1023: 知名端口号, HTTP, FTP, SSH等这些广为使用的应用层协议, 他们的端口号都是固定的
- 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的
常见的端口号:http(80),https(443),ssh(22),ftp(21),mysql(3306)
一个进程是否可以bind多个端口号?
可以!
多个端口唯一标识的是同一个进程,这与端口号用来标识进程的唯一性不冲突。一个端口号是否可以被多个进程bind?
不可以!
端口号是用来表示一个唯一的进程,如果绑定一个已经被绑定的端口号,就会绑定失败。
UDP协议
UDP协议端格式
UDP的报头当中只包含四个字段,每个字段的长度都是16位,总共8字节;
对于UDP的解包直接提取前八个字节就是报头,其他的就是有效载荷;
struct udp_hdr
{
uint32_t src_port:16;
uint32_t dst_port:16;
uint32_t udp_len:16;
uint32_t udp_check:16;
}
UDP数据封装
- 当应用层将数据交给传输层后,在传输层就会创建一个UDP报头类型的变量,然后填充报头当中的各个字段,此时就得到了一个UDP报头
- 此时操作系统再在内核当中开辟一块空间,将UDP报头和有效载荷拷贝到一起,此时就形成了UDP报文
UDP数据分用
- 当传输层从下层获取到一个报文后,就会读取该报文的钱8个字节,提取出对应的目的端口号。
- 通过目的端口号找到对应的上层应用层进程,然后将剩下的有效载荷向上交付给该应用层进程。
UDP的传输是无连接的,不可靠的、面相数据报的;(我只管发送收不收的到不归我管)
面向数据报:
应用层交给UDP多长的报文,UDP就原样发送,既不会拆分,也不会合并;
发送端调用一次sendto,发送100字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节;
UDP如何决定将有效载荷交付给上层的哪一个协议?
应用层每个进程都绑定有端口号,UDP就是通过报头当中的目的端口号(dst_port)来找到对应的应用层进程的
UDP的缓冲区
- UDP没有真正意义上的发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作
- UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃
为什么UDP要有接收缓冲区?
如果UDP没有接收缓冲区,那么就要求上层及时将UDP获取到的报文读取上去,如果一个报文在UDP没有被读取,那么此时UDP从底层获取上来的报文数据就会被迫丢弃;
网络资源是多次的,如果经常因为没有被上层读取报文而丢弃掉,这样十分浪费资源;
UDP会维护一个接受缓冲区,当有报文来到的时候,直接放入UDP接受缓冲区,UDP接收缓冲区当中没有数据那上层在读取时就会被阻塞;
将接收到的报文暂时的保存起来,供上层读取
UDP传输最大长度
UDP协议首部中有一个16位的最大长度. 也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部);
如果需要传输的数据超过64K,就需要在应用层进行手动分包,多次发送,并在接收端进行手动拼装;