TCP TCP 全称传输控制协议(Transmission Control Protocol),是面向连接的、可靠的、基于字节流的传输层通信协议
概念 停止等待协议 A 每发一个包给 B,都必须收到 B 的确认(ACK) ,在规定的时间内 A 没有收到 ACK 包,则重传。
1 停止等待协议有一个问题,如果 B 收到了 A 的包,但是返回的 ACK 包丢失了,此时依然会触发 A 重传
累计确认(累计应答) A同时发送5个数据包,并给这5个数据包序号(seq)(1,2,3,4,5),B再收到数据包后再返回的 ACK 包中返回确认号(ack),表示当前未收到的最小编号。通过这种方式就可以处理停止等待协议
带来的问题。
1 2 3 4 5 6 如果B顺序收到1,2,3,4,5编号的包,那么返回的ack号分别为2,3,4,5,6 如果B顺序收到3,5,1,4,2编号的包,那么返回的ack号分别为1,1,2,2,6 假如3数据包发送时丢包了 如果B顺序收到1,2,4,5编号的包,那么返回的ack号分别为2,3,3,3 如果B顺序收到4,5,1,2编号的包,那么返回的ack号分别为1,1,2,3
流量控制 每个计算机处理能力不一样,如果发送太快,接受太慢怎么办? A、B 在每个数据包中加上一个值,叫窗口大小
(win),表示接收能力
拥塞控制 网络很差时,造成了网络拥塞
,假设拥塞窗口的大小为cwnd,流量控制的滑动窗口的大小为rwnd, 那么窗口大小 = min(cwnd, rwnd)。
慢启动 如何知道拥塞窗口的大小呢?可以采用试探法,先发窗口大小为1的包,如果不丢包,就发送窗口为2、4、8的包,直到出现丢包,从而得到最终的拥塞窗口。
滑动窗口 发送一个数据包过去,不需要等待数据包回来再发送
拥塞机制 一旦出现丢包,就会触发拥塞机制(慢启动、拥塞规避、快速启动、快速恢复)
TCP三次握手
客户端向服务器发出连接请求报文,同部位SYN=1,初始序列号seq=x,此时客户端进程进入了SYN-SENT(同步已发送状态)状态。
服务器收到请求报文后,发出确认报文,确认报文中 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时服务器进入了SYN-RCVD(同步收到)状态。
客户端收到报文后,发出确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。
当服务器收到客户端的确认后也进入 ESTABLISHED 状态,此后双方就可以开始通信了。
为什么是三次 1、防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误,两次握手会使得客户端和服务端再次建立连接,导致不必要的资源浪费。 2、其实也可以说是四次,只是中间两次合并成一次发送了。理由是TCP不允许半连接状态下传输数据。
SYN攻击 客户端在短时间内伪造了大量的IP进行连接,服务器回复响应包,但是源地址是不存在的,所以服务端会不断的重发,直到重发超时。 这些伪造的SYN包将长时间占用未连接队列,影响了正常的SYN,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
1 2 3 4 部分解决方案: 1、延迟TCB分配方法,缓存半连接状态信息,建立连接后在分配 2、增加最大半连接数 3、缩短超时时间
四次挥手
客户端发出断开连接报文,并且停止发送数据。FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),客户端进入FIN-WAIT-1(终止等待1)状态。
服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,服务端就进入了CLOSE-WAIT(关闭等待)状态。这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w。服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
客户端收到服务器的连接释放报文后,发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。必须经过2*MSL(最长报文段寿命)的时间后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。服务器结束TCP连接的时间要比客户端早一些。
为什么要 TIME_WAIT,等待2个MSL后才关闭TCP (2个MSL(Max Segment Lifetime,约240秒))
防止上一次连接中的包,重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
发送的最后一个ack(fin) ,有可能丢失,这时被动方会重新发fin。
为什么是三次握手,四次挥手?关闭一定是四次吗?
连接三次是因为中间两次合并成一次了
TCP是全双工模式,客户端第一次发送FIN报文,只表示不会再请求数据,但此时服务器还可能需要继续发送数据,等服务器数据发送完,服务器才会发送FIN报文。
如果一端发送FIN报文后,另一端不再需要传输数据,那么第二次挥手的ACK报文会和第三次挥手的FIN报文合并发送过去 ,此时关闭连接只需要三次挥手。
客户端突然出现故障怎么处理 服务器每收到一次客户端的请求后都会重新复位一个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
TCP 报文格式
TCP是怎么保证数据可靠性传输的
序列号和确认应答信号
超时重发控制
数据校验
连接管理
粘包、拆包 报文太短,需要合并后发送,报文太长,需要分开发送
解决方案
参考文章 https://www.cnblogs.com/xiaolincoding/p/12732052.html https://www.toutiao.com/i6862639863104012814 https://www.toutiao.com/i6893802302663033355 https://mp.weixin.qq.com/s/Uf42QEL6WUSHOwJ403FwOA