TCP的三次握手
- 服务端新建套接字绑定通信地址,进入LISTEN状态;客户端新建套接字绑定通信地址,调用connect函数,向服务端发送连接请求SYN,并进入SYN_SENT状态,等待服务器确认。
- 服务端监听到连接请求后,就会将连接放入内核等待队列中,并给客户端发送SYN和确认报文段ACK,进入SYN_RCVD状态
- 客户端收到SYN+ACK报文后向服务端发送确认报文ACK,开始读写数据;服务端收到客户端的确认报文ACK后,开始读写数据。
TCP为什么是三次握手而不是两次或四次
- 因为两次不安全,四次没必要。TCP通信要求双方都有数据收发的能力,得到ACK响应后则说明对方具有数据收发的能力,因此双方都需要发送SYN确保对方具有通信能力。
三次握手可以携带数据吗
- 第一、第二次握手不能携带数据,第三次握手可以携带数据。
TCP三次握手失败服务端会怎么处理
- 握手失败的原因有两种
- 第一种(第一次握手)是服务端没有收到SYN,则什么都不做
- 第二种(第三次握手)是服务端回复了SYN+ACK后,长时间没有收到确认报文ACK,超时则会发送RST重置连接报文,释放资源
TCP的四次挥手
- 客户端请求断开连接时会向服务端发送FIN报文,同时进入FIN_WAIT1状态
- 服务端接收到FIN后会给客户端回复一个确认报文ACK,,同时进入CLOSE_WAIT状态。但是自己可能还有数据要发送,客户端同时也需要接收这段数据。客户端接收到ACK报文后会等待服务端数据传输完毕,进入FIN_WAIT2状态。
- 服务端数据发送完毕后,真正调用close关闭连接时,会给客户端发送FIN报文,等待客户端的确认,进入LAST_ACK状态,等待最后一个ACK
- 客户端接收到FIN报文后给服务端回一个ACK报文,进入TIME_WAIT状态,服务端接收到ACK报文后则进入CLOSE状态,断开连接。客户端则需要等待2MSL时间才能进入CLOSE状态,断开连接
为什么要等待2MSL时间
- MSL指的是报文在网络中的最大存活时间。在客户端给服务端发送最后的ACK报文时,这个包可能会到达不了,服务端如果没有接收到这个ACK包,就会重新发送FIN包。所以客户端发送完ACK包后需要等待2MSL的时间,也就是ACK包出去,FIN包进来这一来一回到的时间。如果超过2MSL时间还没有收到FIN包则说明服务端已经收到ACK包,进入CLOSE状态。
为什么TCP握手是三次,而挥手需要四次
- TCP在握手时,其实将SYN和ACK整合为了一个包发送,所以减少了一次包的发送。
- 对于四次挥手,由于TCP是全双工通信,主动关闭方发送FIN请求不表示完全断开连接,只能表示已经不再发送数据了。而接收方可能还要发送数据,就不能立即关闭服务端与客户端的数据通道,所以不能将FIN包和ACK包整合到一起发送,只能先确认ACK报文后,等待服务端无需发送数据后再FIN报文。
TCP为什么能保证数据的有序性?
- 为了保证数据包的可靠传递,发送方必须把数据包保留在缓冲区中
- 并为每个已发送的数据包分配一个序列号
- 接收方利用序列号对接收的数据进行检测,接收到已经顺序化的数据,就将这些数据按照正确顺序重组成数据流发送给高层处理
TCP的超时重传
- TCP协议要求发送端每发送一段报文,就启动一个定时器等待确认信息;若超时还未收到确认信息,TCP就认为报文已经丢失或损坏,需要对报文段重新组织和上传
TCP的滑动窗口机制
- 接收方通过告诉发送方自己的窗口大小,从而控制发送方的发送速度,防止发送方发送速度过快导致自己被淹没
- TCP的滑动窗口解决了端到端的流量控制问题,允许接收方对传输速度进行控制,直到自己有足够的缓冲空间来接收数据
TCP粘包是什么
- TCP粘包指的是发送的若干数据,在到达接收方时,后一个数据包的头紧接这前一个数据包的尾,产生TCP粘包的原因是多方面的,可能时发送方的问题也可能是接收方的问题