传输层位于OSI七层模型的第四层,传输层的主要作用是实现应用程序之间的通信。网络层主要是保证不同数据链路下数据的可达性,至于如何传输数据则是由传输层负责。
传输层协议简介
常见的传输层协议主要有TCP协议和UDP协议。
TCP
TCP协议是面向有连接的协议,也就是说在使用TCP协议传输数据之前一定要在发送方和接收方之间建立连接。一般情况下建立连接需要三步,关闭连接需要四步。
建立TCP连接后,由于有数据重传、流量控制等功能,TCP协议能够正确处理丢包问题,保证接收方能够收到数据,与此同时还能够有效利用网络带宽。然而TCP协议中定义了很多复杂的规范,因此效率不如UDP协议,不适合实时的视频和音频传输。
UDP
UDP协议是面向无连接的协议,它只会把数据传递给接收端,但是不保证接收端是否真正收到了数据。这种特性适合多播、实时的视频和音频传输,因为个别数据包的丢失并不会影响视频和音频的整体效果。
端口号
IP协议中的两大关键要素是源IP地址和目标IP地址。传输层新增了三个要素:源端口号、目标端口号和协议号。
端口号用于区分同一台主机上不同的应用程序。假设你打开了两个浏览器,浏览器A发出的请求不会被浏览器B接收,就是因为A和B具有不要的端口号。
协议号用于区分使用的是TCP还是UDP。
所以:源IP地址、目标IP地址、源端口号、目标端口号和协议号这五个信息只要有一个不同,都被认为是不同的通信。
UDP首部
UDP协议的特点就是简单,它的首部如下图所示:
- 包长度表示UDP首部长度和UDP数据长度之和
- 校验和用来判断数据在传输过程中是否丢失。
TCP首部
TCP首部要复杂得多。解析这个首部的时间也相应的增加,这也是导致TCP连接的效率低于UDP的原因之一。
关键字段解释如下:
序列号:它表示发送数据的位置,假设当前的序列号为s,发送数据长度为I,则下次发送数据的序列号为S + I。在建立连接时通常由计算机生成一个随机数作为序列号的初始值。
确认应答号:它等于下一次应该接收到的数据的序列号。假设当前的序列号为s,发送数据长度为I,则接收端返回的确认应答号为S + I。发送端接收到这个确认应答后,可以认为这个位置以前所有的数据都已被正常接收。
数据偏移:TCP首部的长度,单位为4个字节。如果没有可选字段,那么这里的值就是5,表示TCP首部的长度为20字节。
控制位:长度为8bit,分别有8个控制标志,依次是CWR、ECE、URG、ACK、PSH、RST、SYN和FIN
- CWR
- ECE
- URG
- ACK:改位为1时,确认应答的字段变为有效。TCP规定除了最初建立连接时的SYN包之外改位必须设置为1
- PSH
- RST
- SYN:用于建立连接。SYN为1表示希望建立连接
- FIN:为1时,表示希望断开连接
窗口大小:用于表示从应答号开始能够接收多少个字节。如果窗口为0,可以发送窗口探测
紧急指针:仅仅在URG控制位为1时有效。表示紧急数据的末尾在TCP数据部分中的位置,通常在暂时中断通信时使用(比如Ctrl + C)
TCP握手
TCP是面向连接的协议,连接在每次通信前被建立,通信结束时被关闭。了解TCP连接建立和关闭的过程通常是考察的重点。TCP连接的建立和关闭过程可用下图表示:
三次握手建立连接
- 客户端请求连接SYN
- 服务端确认客户端连接请求
- 客户端确认服务端已收到连接请求,建立连接开始通信
为什么是三次握手
三次握手的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”
这是因为在网络请求时,我们时刻要注意“网络是不可靠的,数据包是可能丢失的”。假设没有第三次确认的情况下,客户端向服务端发送SYN,请求建立连接。由于延迟,服务端没有及时收到这个包。于是客户端重新发送一个SYN包。
假设服务端接收到了第二个SYN包,建立了通信,一段时间后通信结束,连接被关闭。这是最初被发送的SYN包抵达服务端,服务端又会发送一次ACK确认。由于两次握手就建立连接,此时的服务端就会建立一个新的连接,然而客户端认为没有请求建立连接,所以就不会向服务端发送数据,从而导致服务端建立一个空连接,浪费资源。
ACK确认包丢失怎么办?
三次握手其实解决了第二步的数据包丢失的问题,那么第三步的ACK确认包丢失后,TCP协议是如何处理的呢?
按照TCP协议处理丢包的一般方法,服务端会重新向客户端发送数据包,直至收到ACK确认为止。但实际上这种做法有可能遭到SYN泛洪攻击。泛洪攻击,是指发送方伪造多个IP地址,模拟三个握手的过程。当服务器返回ACK后,攻击方故意不确认,从而使得服务器不断重发,由于服务器长时间出于半连接状态,最后消耗过多的CPU和内存资源导致死机。
正确的处理方法是服务端发送RST报文,进入CLOSE状态。这个RST数据包的TCP首部中,控制位中的RST设置为1.这表示连接信息全部初始化,原有的TCP通信不能继续进行。客户端如果还想重新建立TCP连接,就必须重新开始第一次握手。
## 四次握手关闭连接
- 客户端发送FIN通知服务端 客户端要关闭连接
- 服务端发送ACK确认客户端关闭连接
- 服务端发送FIN通知客户端 服务端要关闭连接
- 客户端发送ACK确认服务端关闭连接
由于连接是双向的,所以双方都要主动关闭自己这一侧的连接。