应用层协议是请求与响应服务,客户端的请求与服务器的响应是通过应用层传输到网络中的,但再实际上,应用层并不能直接通信,需要将数据进行报头的封装,向下层交付,贯穿整个协议栈。我们已经谈到应用层协议负责应用。往下层交付,我们又要考虑交给谁?浏览器接收到请求后,同样要经过协议栈,并且需要知道将数据交到哪一个应用。
在协议中,我们始终要考虑,数据如何向上交付,报文和有效载荷如何分离的问题,还要考虑粘包等问题。
本文介绍距离应用层最近的传输层,负责数据从发送端送到接收端。
传输层协议有UDP和TCP,UDP是不可靠连接,不考虑数据丢失,正因如此,UDP协议很简单,并且资源浪费小。而TCP协议必须考虑大量数据丢失的问题,十分的负责,必然的代价是资源的消耗(空间和时间上)。
从了解UDP协议。
端口号
之前说过,端口号是用来标记主机上唯一的一个进程。数据在网络传输中,必须要解决上层交付的问题,因此传输中必定会获取到上层标志进程的唯一标志,就是端口号。所以端口是传输层的概念,主要负责向上交付的问题。
传输层获取到应用层的数据后,必定会添加端口相关的报头
同样传输层向上交付数据时,也必须解析出目标端口和源端口,向上交付有效载荷。
五元组标志通信
在TCP/ip协议中,通过源端口,目的端口,源ip,目的ip,及协议号。这个五元组就能双方通信。
查看五元组
常用的方式是netstat - nltp a u
介绍选项:
- n:把字符显示成数字
- l:查看监听状态的服务,去掉" l ",就能查看所有状态
- u:查看udp协议
- t:查看tcp协议
- a:显示所有的选项,默认不显示LISTEN相关
- p:查看进程
端口号的划分
0-1023号是知名端口,普通用户是不能绑定的。
1024-65535是可以被OS分配的动态端口号。
UDP协议
UDP协议是一中无连接的协议,它不像TCP协议在通信前需要建立连接。这种特性使得UDP在对时实性能要求比较高,对数据丢失容忍度高的场合有极高的运用。如视频流,电话通信等。
UDP报文传输都是独立的,每一个UDP都被封装成独立的数据报,数据报中必然包含着源端口,目标端口。
UDP协议格式
udp协议的基本格式如下:
源端口:数据从哪里来
目的端口:数据交付到哪里
udp长度:包括报头和有效载荷
校验和:如果UDP报文出错,就直接丢弃
报头和有效载荷分离的问题?
UDP的报头是四个字段,每一个字段是16位。因此读到8字节后,就代表读完报头。继续读取到结尾,就读完有效载荷,就能做到报头和有效载荷的分离。
数据如何向上交付的问题?
获取到有效载荷后,就要将数据往上层交付,在上层中有大量的协议进程,具体交到哪一个进程呢,主要是目的端口决定的!获取到目的端口后,就能交付。
如何理解报头
报头的本质就是一个结构化字段,必然也是数据。其实就是一个结构体。
数据的封装
传输层收到应用层发来的数据后,会在传输层创建udp_header报头类型的变量,并且填充相应的字段。接着在OS开辟一块空间,将报头和有效载荷封装到一起,并直接发到下一级。
因此udp的传输层是没有缓冲区的,报文是直接向下交付的。
报文的管理
udp没有发送缓冲区,必然的结果是数据一旦被封装就直接发送到对方的主机上,对方主机就会一下子收到大量的报文,必然会来不及处理。所以必须对报文进行管理。OS怎么管理呢?先描述,再组织。
实际上就是一个队列,如果有报文发来,就先维护起来,列入队列中sk_buff 。要处理数据时,就往队列中取出对头的数据去处理。
UDP协议的特点
udp协议就像寄信:
- 无连接:知道对端的主机和端口就能直接通信,无需要建立连接。TCP有三次握手,是面向连接。
- 不可靠:没有确认机制,没有重传。如果数据校验不一致,就直接丢弃这个报文。
- 面向数据报:不能控制读取的大小和次数。
面向数据报
应用层交付给UDP一个报文,报文封装后就直接发送到对端。
不会囤积报文,或者分割报文。
对端必须一次收完一个完整的报文。
比如一份udp报文有10个字节:
发送端会立刻调用sento发送报文。接收方会调用recvfrom,一次性接收10个字节。这样就解决了粘包的问题。
接收方的报文天然就存放着数据报的长度,所以依靠数据报就能实现有效载荷和报文的分离,能够知道有效负载的长度。
基于UDP的应用层协议
- NFS:网络文件系统。
- TFTP:简单文件传输协议。
- DHCP:动态主机配置协议。
- BOOTP:启动协议(用于无盘设备启动)。
- DNS:域名解析协议。
UDP的使用场景
- 实时视频流和音频流传输,如在线直播、视频会议等;
- 实时游戏,如在线游戏中的游戏数据传输;
- 简单的请求/响应交互,如 DNS、SNMP 等;
- 广播通信,如广播、多播等;