1.概述

1.1TCP的概念
TCP是面向连接的、可靠的、基于字节流的传输层通信协议。
面向连接的:只支持一对一通信,无法像UDP那样一对多,
可靠的:无论网络链路出现什么链路变化,TCP都能保证报文一定能够到达接收端
字节流:表示发送的数据是可以没有边界的,也就是说无论数据有多大,我们都可以进行传输,并且消息是有序的(通过序列号实现),收到重复的报文会抛弃掉。
1.2字段说明
序列号:其初始值为建立连接时在计算机生成的随机数,通过SYN爆发送给对端主机时,每发送一次就会累加一次数据字段的字节数大小,用于解决网络包乱序的问题。
确认号:接收端收到这个确认应答后,就可以认为过去发送的数据包种,序号小于这个确认号的数据都已经被正确接收。用于解决丢包问题。
6个控制位:
①URG:紧急标志位,表示这个报文段种有紧急数据,紧急数据全部排在普通数据前,配合紧急指针使用。接收端接收到此保温后必须先处理紧急数据,然后再去处理普通数据。
②ACK:ACK==1时表示“确认应答号”字段有效,出了最初建立连接时的SYN包以外,其余包的ACK位必须为1
③PSH:催促标志位,当发送端将报文的PSH置为1时,发送端会立即发送该报文,不会等待缓冲区满后再发送。接收端接收到PSH为1的报文时,也会立即交付给上层,不会等待缓冲区满后再交付。
④RST:复位请求位,RST==1时表示连接出现错误,必须强制断开连接。
⑤SYN:SYN==1时表示希望建立连接,其报文中的“序列号”字段为初始值。
⑥FIN:FIN==1时表示没有此后不再有数据发送,希望断开连接,此时需要双方进行四次握手后断开连接。
2.三次握手
2.1三次挥手的过程

注:第三次握手可以携带数据,前两次不能
2.2为什么需要三次握手才能建立TCP连接
①避免初始化历史连接(主要原因)
RFC 793原文:“The principle reason for the three-way handshake is to prevent old duplicate connection initiationsfrom causing confusion.”
百度翻译:“三方握手的主要原因是防止旧的重复连接启动造成混乱”
由上图可知,如果只有两次握手,那么服务端就会为Seq Num == 123的那次请求建立连接,然而客户端希望的是为Seq Num = 456的那次请求创建连接,最终导致双方创建链接失败。
因此需要第三次握手来判断当前连接是否为历史连接,因为在客户端中有充足的上下文来判断当前连接是否为历史连接。如果是,客户端会发送一个RST报文,以此中止历史连接。如果不是,则发送ACK报文,使通信双方成功建立连接。
②双方同步初始序列号
在使用TCP协议传输数据的过程中,双方都必须各自维护一个“序列号”,这个序列号是维护可靠性的关键字段,通过这个序列号可以实现:(1)接收方去除重复数据;(2)接收方可以对数据进行排序;(3)接收方通过给确认号赋值(确认号=序列号+1),发送方就可以辨别哪些数据已经被对方正确接收。
通过双方互发自己的序列号以及确认应答号,最终双方的初始序列号能够被可靠地同步。
③避免资源浪费
假设我们进行四次握手如下所示,那么就可以发现第二次与第三次握手可以合并到一次中,从而避免资源的浪费。
不用两次握手的原因已在①中已经说明。
补充:
为什么双方的初始序列号不同:
为了安全性,避免接收黑客伪造相同序列号的TCP报文。
3.四次挥手
3.1四次挥手的过程

3.2为什么需要四次挥手:
第一次挥手:表示发起端不再发送数据了,但还可以接收数据
第二次挥手:表示接收端已经知道对方已经不再发送数据,但是接收端可能还有数据需要处理或者发送
第三次挥手:表示接收端的数据已经全部处理并发送完毕,接下来都不会再发数据。
第四次挥手:表示发起端已经知道对方不再发送数据,接收方收到后立即关闭该连接并回收资源,发起端自发送第四次挥手报文起,等待2MSL后再关闭连接并回收资源。
3.3为什么发起端需要等待2MSL:
MSL(Maximum Segment Lifetime,报文最大生存时间)是任何报文在网络上能够存在的最长时间,超过这个时间后报文就会被抛弃。
比较合理的解释为,在四次挥手的过程中,假如接收方没有收到第四次挥手所发送的ACK,那么接收方就会重发第三次挥手中的FIN报文,一来一去最多2MSL,当发起方再次接收到FIN报文时会重新计时2MSL。
除此之外,假如在第二次挥手ACK报文与第三次挥手FIN报文之间,亦或者发起四次挥手之前,接收端还发送了普通数据报文,但第三次挥手FIN报文先一步抵达发起段,在2MSL时间内发起端必然能正确接收之前普通数据报文。
如果TIME_WAIT时间过短甚至没有,那么就会导致两个问题。第一个问题:假设第四次挥手的ACK报文在网络中丢失,那么接收端就会一直处于LAST_ACK的状态,如果此时有新的连接请求抵达,那么接收端只能返回RST错误报文。
第二个问题:有可能在下一次相同的两端重新建立TCP连接后,接收端直接重用了旧的TCP连接,也就是说接收端沿用了之前的序列号,那么此时旧的普通数据包抵达发起端,那么发起端就会接受了错误的TCP报文。
如果TIME_WAIT的时间过长,那么也会导致出现问题,因为连接的维护是需要资源的,如果长时间没释放那么就会导致资源的浪费,最重要的是端口资源的浪费,TCP连接至少要消耗掉1个本地端口,如果TIME_WAIT状态过多,占满了所有端口资源,那么就导致无法创建新的连接,这可能会导致非常严重的问题(其实占满端口资源已经非常严重了)。
4.重传机制
4.1超时重传
4.2快速重传
4.3 SACK
4.4 D-SACK
5.滑动窗口机制
补充
既然IP层可以分片,为什么TCP还需要MSS呢
先分别认识一下MTU和MSS的概念
MTU:IP头部加上传输层的数据(当前情况为TCP报文)的最大长度,MTU在以太网中一般为1500字节;
MSS:TCP报文中,除去头部后的数据部分的最大长度。
当IP层中出现大于MTU的数据(TCP头+TCP数据)时,那么IP就要进行分片,虽然这看起来跟TCP层类似,但IP层出现某个分片丢失时,需要该TCP报文下的将所有分片都重传一次。
并且IP层本身没有超时重传机制,该功能又传输层的TCP协议来实现。
因此IP层进行分片传输是低效的。
