【网络】传输层协议——TCP协议

TCP协议

TCP全称为“传输控制协议((Transmission Control Protocol)”,即对数据的传输进行一个详细的控制;

1.TCP协议段格式

                    

  • 源端口号:表示发送端口号,字段长度16位;
  • 目标端口号:表示接受端口号,字段长度16位;
  • 序列号:字段长32位,序列号是指发送数据的位置,没发送一次数据,就累加一次该数据字节数的大小;
  • 确认应答号:字段长32位,是指下一次应该收到的数据的序列号。
  • 数据偏移:该字段表示TCP所传输的数据部分应该从TCP包的哪个位开始计算,当然也可以把它看做TCP首部的长度;
  • 保留:该字段主要是为了以后扩展时使用,长度为4位,一般设置为0,但即使收到的包在该字段不为0,此包也不会被丢弃;
  • 控制位:字段长8位,主要有以下6个标志位: 

URG:紧急指针是否有效

ACK:确认号是否有效

PSH:为1时,表示需要将受到的数据立刻传给山城应用协议,为0时,则不需要立即传而是先进行缓存

RST:对方要求重新建立连接;我们携带RST标识的称为复位报文段

SYN:请求建立连接;我们把携带SYN标识的称为同步报文段

FIN:通知对方,本段要关闭了,我们称携带FIN标识的为结束报文段

  • 窗口大小:字段长为16位,    用于通知从相同TCP首部的确认应答号所指位置开始能接受的数据大小(8位字节)
  • 校验和:字段长为16位,发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含                 TCP数据部分;
  • 紧急指针:字段长16位,标识哪部分数据是紧急数据;

2.确认应答机制

利用序号+确认序号实现

3.超时重传机制

TCP内部实现,动态计算的。以单方向数据传输最大时间*2作为超时时间(发送一次,接受一次确认应答)

博客:TCP的确认应答机制和超时重传机制

4.连接管理机制

三次握手和四次挥手

博客:TCP的三次握手和四次挥手

5.滑动窗口

  • 作用:提高网络传输效率
  • 原理:一去一回串行的网络数据传输,转变为并行的收发数据;通过序号+确认号保证数据传输的安全性;
  • 窗口:无需等待确认应答二可以继续发送数据的最大值
  • 滑动:并行发送数据报,需要接收到ACK的响应报文段才表示数据发送成功。而窗口是否能够滑动,以及能够滑动到哪个位置都由ACK响应报文的下一个序号决定,具体是能滑动ACK相应的报文连续的最大确认序

博客:TCP的滑动窗口以及包丢失的重传问题

6.流量控制

背景:接受端能力有限,如果接收缓冲区被打满,会造成丢包等一系列问题;

原理:使用窗口大小字段,告诉发送端发送数据的大小

7.拥塞控制

背景:不清楚当前网络状态的情况下,贸然发送大量的数据,可能引发网络拥堵雪上加霜

原理:

(1)慢启动机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据

(2)拥塞窗口初始值为1,开始呈现为指数曲线,到达后阈值变为线性增长;

博客:TCP的流量控制和拥塞控制

8.延迟应答

作用:提高网络传输效率

原理:接收到数据报时,不马上响应ACK,而是延迟一段时间后再应答,这样可以增加滑动串口的大小。提高系统吞吐量

9.捎带应答

作用:提高网络传输效率

原理:合并发送数据报

博客:TCP的延迟应答和捎带应答

10.面向字节流

面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只能发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

创建一个TCP的socket,同时在内核中创建一个发送缓冲区和一个接受缓冲区

  • 调用write时,数据会先写入发送缓冲区中;
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出;
  • 如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去;
  • 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区;
  • 然后应用程序可以调用read从接受缓冲区拿数据;
  • 另一方面,TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据,这个概念叫做全双工;

由于缓冲区的存在,TCP程序的读和写不需要一一匹配。

写100个字节数据时,可以调用一次write写100个字节,也可以调用100次write,每次写一个字节;

读100个字节数据时,也完全不需要考虑写的时候是怎样写的,既可以一次read100个字节,也可以read一个字节,重复100次;

11.粘包问题

  • 首先要明确,粘包问题中的“包”,是指的应用层的数据包;
  • 在TCP的协议头中,没有如同UDP一样的“报文长度”这样的字段,但是有一个序号这样的字段;
  • 站在传输层的角度,TCP是一个一个报文过来的,按照序号排好序放在缓冲区中;
  • 站在应用层的角度,看到的只是一串连续的字节数据;
  • 那么应用程序看到了这么一连串的字节数据,就不知道从那个部分开始到哪个部分,是一个完整的应用层数据包;

如何避免粘包问题呢?归根结底就是一句话:明确两个包之间的边界。

  • 对于定长的包,保证每次都按固定大小读取即可;
  • 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
  • 对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序员自己来定的,只要保证分隔符不和正文冲突即可)

对于UDP协议,是否也存在“粘包问题”?

  • 对于UDP,如果还没有上层交付数据,UDP的报文长度仍然在,同时,UDP是一个一个把数据交付给应用层,就有很明确的数据边界;
  • 站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收,不会出现“半个”的情况。

12.TCP异常情况

进程终止:进程终止会释放文件描述符,仍然可以发送FIN,和正常关闭没有什么区别;

机器重启:和进程种植的情况相似;

机器掉电、网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接不在了,就会进入reset,即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放;

另外,应用层的某些协议,也有一些这样的检测机制,例如HTTP长连接中,也会定期检测对方的状态,例如QQ,在QQ断线之后,也会定期尝试重新连接。

13.TCP总结

保证TCP的可靠性:

  • 校验和
  • 序列号(按序到达)
  • 确认应答
  • 超时重传
  • 连接管理
  • 流量控制
  • 拥塞控制

提高性能:

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

其他:

  • 定时器(超时重传定时器,保活定时器,TIME_WAIT定时器等)

14.基于TCP应用层的协议

  • HTTP
  • HTTPS
  • SSH(加密的远程登录系统)
  • Telnet(远程终端接入)
  • FTP(文件传输)
  • SMTP(电子邮件)