TCP协议是传输层一个非常重要的协议。
下面从四个方面介绍TCP协议:
- TCP头部信息。
- TCP状态转移过程。TCP连接的双方都是一个状态机。
- TCP数据流以及数据流的控制(超时重传,拥塞避免等)
TCP特点
TCP和UDP都是传输层的重要协议,TCP相对于UDP具有以下特点:面向连接、字节流和可靠传输。
TCP连接是全双工、一对一的。
TCP使用的是字节流服务,即 发送端的写操作和TCP模块发送出去的TCP报文段的个数没有数量关系,接收端的读操作和TCP模块接收的TCP报文段也没有数量关系。也可以说:发送端的写操作的次数和接收端读操作的次数之间没有任何数量关系。
而UDP使用的是数据报服务,即每次读或者写操作对一一对应一个数据包的发送和接收。

TCP的传输是可靠的。首先TCP协议采用的是发送应答机制,即发送端每次发送信息都必须接收到接收端的应答 才视为发送成功。其次TCP还采用了超时重传机制。最后TCP报文段最终是以IP数据发送的,而IP数据报到达接收端可能乱序和和重复(IP协议是非可靠传输),所以TCP协议会对接收到的TCP报文段进行重排、整理再交付给应用层。
TCP头部结构
TCP头部结构包括20字节的固定结构和最多40字节的选项部分,所以整个头部最多60字节,最少20字节,

16位端口号:表明发送端和接收端的端口号。端口号不是IP地址,只是这个IP地址下的某个端口的标号(一般为0~65535)。只有将**"源IP地址+源端口"与 "目的IP地址+目的端口"结合,才能唯一确定一个 端到端的通信会话**,这个组合在TCP/IP中被称为套接字(Socket)。

序号=上一次对方的确认号

确认号=上次对方的序号+上次对方发送来的数据
4位头部长度:表示该TCP头部有多少32bit(4Byte)。因为4位最大可以表示15,所以TCP头部最多有60字节。

只有承载数据、SYN、FIN 的报文才占用序号,纯 ACK 报文不占。SYN、FIN 的报文占用一个序号。

TCP选项,此处不展开讲。
序号(seq),确认号(ack)的计算:
序号(seq)=上一次对方的确认号
确认号(ack)=上次对方的序号+上次对方发送来的数据
只有承载数据、SYN、FIN 的报文才占用序号,纯 ACK 报文不占。SYN、FIN 的报文占用一个序号(即一个数据)。
TCP状态转移

MSL : 报文最大生存时间.
当系统中出现大量的TIME_WITE,是因为 服务端主动断开了连接。
三次握手四次挥手的示意图,以及状态转移说明。还有四次挥手在半关闭状态下的数据传输。

延迟确认
客户端针对服务器返回的数据所发送的确认报文段都不携带任何其他数据,而服务器每次发送的确认报文段都携带一些需要发送的数据,这种情况称之为 延迟确认。即 服务器不马上确认上次收到的数据,而是延迟一段时间观察是否还有需要发送的数据,如果有就将确认报文段和数据一起发送过去。
延迟确认可以减少发送TCP报文段的数量。
在本地回路还有局域网上都有基本相同的结果,但在光宇网上,交互的数据流可能有很大的延迟还有很多微小的报文段,如果严格按照延迟确认很容易产生拥塞发生。所以一般使用Nagle算法解决。
Nagle算法:要求一个TCP连接的通信双方在任意时刻都最多只能发送一个未被确认的TCP报文段,在该报文段的确认到达前不能发送其他的报文段。另一方面,发送方在等待确认的同时收集本端需要发送的微量数据,并在确认到来时以一个TCP报文段将他们全部发送出去。
超时重传
TCP服务必须重传 规定时间内没有收到确认的 TCP报文段。会有一个重传定时器专门负责计时。每次重传的时间间隔都会翻倍,比如0.2,0.4,0.8,1.6......重传的次数默认为3,重传间隔和重传次数都可以修改。
拥塞控制
SWND:发送方一个窗口内的最大数据量。
SMSS:单个报文段的最大数据量。
如果SWND太小,会出现明显的延迟,如果SWND太大,会出现网络拥塞。
所以引入拥塞窗口CWND。
ssthresh:慢启动门限。
CWND初始等于一个SMSS
当CWND<ssthresh时,CWND翻倍增长,呈指数级增长。
当CWND>ssthresh时,CWND每次增长一个SMSS,呈线性增长。
当发生网络拥塞时,就调整ssthresh的值,为发生网络拥塞时CWND的二分之一。

快速重传
