目录
🍀🍂TCP报文结构
🍂确认应答
🍂超时重传
TCP报文结构
与UDP相同都是传输层协议,其数据报结构也可以整体分成:报头+载荷。
报头里有源端口号和目的端口号,数据式应用层封装的数据。我们知道TCP是可靠性传输,所谓可靠性传输这一点在上一篇文章中解释过 (http://t.csdn.cn/HAO4u)。那么为了尽力完成可靠性传输,TCP数据报中还有32位序号和32位确认序号。都是辅助TCP完成可靠性传输的。
TCP如何实现可靠性
确认应答
通过传递一个应答报文(ack)来确定是否将消息发送成功。
超时重传
真实的网络环境相当复杂,相互传输信息的两端中间还有非常多的其他设备,客户端发的某条消息需要在网络环境中层层封装,再层层分用,最后到达服务器。反之服务器给客户端传消息也是同理。假如在某一时刻有非常多的消息经过某个设备,使得这个设备的流量达到了峰值,就可能造成数据的丢失,也就是丢包。
如果出现丢包,导致发送方的消息发送失败,接收方收不到消息自然也就不会发送ack,当发送方迟迟收不到ack,就会认为是消息丢包了,就会重新发送一遍,也就是超时重传。
数据在传输过程中都有可能造成丢包,所以不管是一般的数据报还是返回的ack数据报,都是有可能丢包的,所以发送方/接收方触发超时重传的原因有:
发送方丢包
如果是发送方消息丢包, 发送方迟迟收不到ack,就会触发超时重传。这种情况一般没什么影响。
接收方返回的ack丢包
这种情况下,即使发送方发送的消息发送成功了,但是接收方返回的ack丢包了,发送方接收不到返回的ack,也仍然认为是消息发送失败,触发超时重传,重新发送消息,直到接收到返回的ack。
这种情况在某些场景就会造成严重的影响,试想一下,如果是转账,付款的人明明已经将钱付过去了,但是收款人这边说没有收到,那么付款一方还需要再次付一次款。这样就会给付款的人造成损失。
针对上述问题,TCP的设定是,在接收方会有一个接收缓存区,接收到的消息不会马上就处理,而是放到这个接收缓存区中,然后TCP会根据收到的序号进行自动去重。
TCP连接管理
建立连接(三次握手)
我们知道TCP是有连接传输,发送方和接收方进行信息交互需要建立连接,不在进行信息交互许需要断开连接。
建立连接的过程可以总结成三次握手:
客户端发给服务器一个带有syn(同步报文段,意思是一方要向另一方建立连接)的数据报,服务器收到后返回一个ack,同时服务器也要像客户端发送一个syn建立连接,【需要注意的是,建立连接的过程都是内核完成的,所以服务器返回ack和发送syn的过程可以视为同步,也就会在一次发送中携带两个报文段。】客户端收到后返回一个ack,服务器收到后整个建立连接的过程完成。
断开连接(四次挥手)
客户端发送一个FIN(结束报文段),服务器收到后返回ack,然后将服务器当前执行的逻辑处理完后(scoket.close)再给客户端发送FIN,客户端收到后返回ack,服务器收到后断开连接完成。
断开连接过程能否是三次挥手,其实在某些情况下断开连接的过程就是三次挥手,原因是正常来说服务器需要将当前执行的代码逻辑处理完(scoket.close)后才断开连接,如果恰好逻辑处理完了,客户端的断开连接FIN也发过来了,此时服务器就会返回一个ack+FIN,也就变成三次挥手了。