一、概述
- 概念:传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
- TCP最主要的特点:
(1)TCP是面向连接的运输层协议。
(2)每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的。(ps.端点即socket套接字,socket = (IP : 端口号) )
(3)TCP提供的服务是可靠的。
(4)TCP提供的是全双工的通信。
(5)面向字节流。
TCP发送消息所采用的方式与UDP完全不同,它是面向字节流的传输协议,根据通信的对方给出的窗口值和网络拥塞的情况来决定发送的数据数量。
二、TCP报文的首部格式
TCP虽然是面向字节流的协议,但它的数据单元是报文段,TCP报文段由头部和数据组成,其中头部包含着传输所需要的所有功能。
TCP首部的前20个字节是固定的,后面的根据需要再添加:
- 源端口与目的端口:写入发送方和接收方的端口号,各占2个字节。
- 序号:标明这次传输的报文段从第几个字节开始,占4个字节。
- 确认号:期望收到对方下一个报文段的起始字节序号,占4个字节。
- 数据偏移:指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。占4个字节。(ps.就是说数据在报文段的第几个字节才开始。)
- 保留:保留着以后用。目前置为0。
以下的六个字段都是标志位,只有0和1的值。
- URG:如果报文段中包含着紧急数据,该字段置为1,即告诉系统应尽快传送此报文段(该报文段可以插队)。如果URG=1,应结合紧急指针给出的紧急数据的位置,把它插入到本报文段的最前面。
- ACK:如果ACK=1,确认号才有效,为0时确认号是无效的。(ps.TCP规定,在连接建立后所有传送的报文段都必须置ACK为1)
- PSH:如果发送方希望在发送完此报文段之后立即收到接收方的响应报文,就置PSH=1,接收方收到后就不会等到缓存满了之后再发送,而是直接发送现有数据。
- RST:如果RST=1,代表需要重新建立连接,即先释放当前连接,再建立连接。(ps.TCP连接中出现了严重差错,或者拒绝非法的报文,拒绝打开连接。)
- SYN:如果这是一个请求连接或者接受连接的报文,SYN应置为1。
- FIN:如果要释放一个连接,FIN应置为1。
- 窗口:给出接收方回应报文应控制在多大范围里。即窗口值就是现在的发送方的接收缓存能容纳的字节数。占2字节。
- 检验和:在发送端将发送的字节转成16位的二进制,求出各个字节的二进制之和。注意,如果加的时候出现了最高位的溢出,要进行回卷(即将溢出的高位数与剩下的低位数相加),再将得到的数字进行反码运算,即得到了检验和。随后在接收端将收到的数据和检验和相加,如果和全为1,代表没有出错;否则(有一位为0),在传输时发生了错误。占2字节。
- 紧急指针:只在URG=1时才有意义,它标明了紧急数据末尾在报文段中的位置。占2字节。
- 选项:选填的,最多占40字节。
三、TCP如何建立连接
1.三次握手
TCP建立连接的过程又被叫做三次握手,如图所示: 在最开始时,A和B都处于CLOSED状态。
第一次握手:A握手:A发送请求B的报文到服务器,其中:
SYN=1(请求连接),seq=x(从第x个字节发送数据)
因A的请求连接B会进入LISTEN状态;而A发送请求报文之后会进入SYN_SEND状态,等待B的确认。
第二次握手:B握手:B收到请求报文,确认SYN=1。然后发送一个响应报文,其中:
SYN=1(同意连接),ACK=1(ack有效),seq=y(从第y个字节开始发送),ack=x+1(期望A发送第x+1个字节开始的数据)
此时B进入SYN_RECV状态。
第三次握手:A握手:A收到B的响应报文,向B发送再次确认报文,其中:
ACK=1(ack有效),seq=x+1(从第x+1个字节开始发送),ack=y+1(期望B发送第y+1个字节开始的数据)。
发送完毕后A和B都进入ESTABLISHED状态,此时A和B已建立好连接。
2.第三次的握手的必要性
假如A发送的请求消息滞留了,重传机制会重新发送消息给B,B接收并发送给A确认信息,如果这时A没有了再次确认的动作,即第三次握手的动作,那么这次连接就会建立成功。可是之前滞留的那条消息出来了,按目标端口号依然发送给了B,不知情的B再次发送给A一个确认的信息,这就导致了一个错误的连接。
所以第三次的握手动作,可以验证当前是否真的需要通信,不需要就不会进行第三次的握手。
四、TCP如何释放连接
1.四次挥手
TCP释放连接的过程又被叫做四次挥手,如图所示:
在数据都发送完毕后,TCP需要释放连接。在释放开始前,双方都处于ESTABLISHED连接状态。
第一次挥手:A挥手释放:A发送请求释放连接的报文,其中:
FIN=1(释放连接),seq=u*(从第u个字节开始)
此时A进入FIN-WAIT-1状态,等待B的确认。
第二次挥手:B挥手确认:B发送确认A释放连接的报文,其中:
ACK=1(ack有效),seq=v(从第v个字节开始),ack=u+1(期望第u+1个字节开始)
此时B被通知到了A的释放请求,B被动关闭,进入CLOSE-WAIT状态。
(而收到此条确认报文的A会进入FIN-WAIT-2状态。)
第三次挥手:B挥手释放:B也确认释放连接,发送报文给A,其中:
FIN=1(释放连接),ACK=1(ack有效),seq=w(从第u个字节开始),ack=u+1(期望第u+1个字节开始)
此时B进入LAST-ACK状态,等待A的最后确认。
注意:如果B没有进行第三次的挥手,即B自己并不想释放连接,A就会进入半关闭的状态。
第四次挥手:A挥手确认:收到B释放的报文,A进入TIME-WAIT状态。A发送确认B释放的报文,其中:
ACK=1(ack有效),seq=u+1(从第u+1个字节开始),ack=w+1(期望第w+1个字节开始)
注意:
(1)如果B没有收到最后一次的A的ACK确认信息,就会引发重传机制,B会重新发送FIN。
从而保证了A发送的ACK确认信息一定会到达B。
(2)保证本次连接所产生的所有报文段都可以在2MSL中从网络中消失。
2.为什么断开连接是四次挥手
因为TCP是全双工的,所以双方都要发送请求释放的信息,对方进行确认,所以是四次。
3.为什么在断开连接之后还要等待2MSL时间
(1)为了保证A发送的最后一个确认报文能够到达B:如果B没有收到最后一次的A的ACK确认信息,就会引发重传机制,B会重新发送FIN+ACK,而A就能在2MSL时间内收到这个重传的报文段。如果A在接收到B的释放报文段后就立即进入CLOSED关闭状态,就不会接收到B的重传报文,B也就会因收不到A的确认报文而一直无法正常关闭。
(2)保证本次连接所产生的所有报文段都可以在2MSL中从网络中消失,不会让下一个新的连接中出现旧的连接请求报文段。
五、TCP的可靠性
tcp通过以下7点保证可靠性:
1.检验和
检验和用来避免将消息发送给错误的接收方。TCP首部校验和计算三部分:TCP首部+TCP数据+TCP伪首部。
发送端:
首先,把伪首部、TCP报头、TCP数据分为16位的字,如果总长度为奇数个字节,则在最后增添一个位都为0的字节。把TCP报头中的校验和字段置为0。
其次,用反码相加法(对每16bit进行二进制反码求和)累加所有的16位字(进位也要累加,进位则将高位叠加到低位)。
最后,将上述结果作为TCP的校验和,存在检验和字段中。
接收端:
将所有原码相加,高位叠加到低位, 如计算结果的16位中每一位都为1,则正确,否则说明发生错误。
注意:检验和可以避免将消息发送给错误的接收方,但是不能把发错的消息重新收回再发送给正确的接收方。对于接收方来说依然是没有收到消息。
2.序列号
tcp将每个字节的数据都进行了编号,也就是序列号。
序列号的作用:
a.保证可靠性(接收到的数据少了某个序号的数据时,马上能知道)
b.保证数据的按序到达
c.提高效率,可实现多次发送,一次确认列号来实现。(ack,seq)
3.确认应答机制(ACK)
当ACK=1时确认首部的确认字段有效。进行确认时,确认字段值表示这个值之前的数据都已经按序到达了。而发送方如果收到了已发送的数据的确认报文,则继续传输下一部分数据,而如果等待了一定的时间还没有收到确认报文就会启动重传机制。
4.重传机制
(1)超时重传机制:当每发送一个数据段时就会启动一个重传计时器,如果在计时器到时之后依然未收到ack确认,那么会立即重传这个数据。
(2)快重传:超时重传机制效率低,所以发展出快重传机制。 他与超时重传机制并存。(计时器先到时就用超时重传,先确认重传M3就用快重传,他们是同时存在的。)当快重传算法开始施行以后就不需要等到收到上一次数据的确认数据就可以发送。 没有按序收到的m4,m5这些也会保存在接收方但是不会引起滑动窗口右移,而是直到数据全部有序之后窗口才右移。