编程知识点iOS进阶iOS Developer

[记录] iOS网络编程 - socket状态机TIME_WA

2016-09-02  本文已影响0人  ck2016

问题发生场景

在做app客户端tcp掉线自动重连的时候,我把一个 socket 对象在应用层断开了,然后我考虑到内存碎片问题(内存的内部碎片,外部碎片),就没有释放这个socket,而是直接用它再去连接其他服务器,发现连不上,我向这个socket写任何数据都没有反应!然而我申请一个新的socket去连接,又一切正常。

为什么向断开的socket再写数据就没有任何回应了呢?

原因

经过一番查找终于找到了原因,socket断开之后,会进入一个叫TIME_WAIT的状态,该状态会持续4到5分钟,在这个状态内,socket不会收发任何来自应用层的数据,看下图(图片来源于网络)


4次挥手.png

看上图,客户端在发出最后一个ack包之后,进入了 TIME_WAIT 状态!
因为最后一个 ack 可能会丢失,如果丢失后会触发服务器tcp超时重传机制,导致服务器再发个 FIN 包给你,所以要进入 TIME_WAIT 等待4分钟,确保网络上没有残余的 FIN 包,才能进入 CLOSED 状态,进行下一次连接。在 TIME_WAIT 状态中不能建立新的连接,假设你建立新的连接,可能会收到服务器超时来的FIN包,会断掉的。

为什么是等待4分钟,因为有个最大生存时间MSL,最后一个ack包过去需要一个MSL,服务器重传一个FIN包需要一个MSL,加起来就是 2MSL,一个MSL大约2分钟,两个就是4分钟。所以4分钟后,tcp就能够确定网络上没有FIN包了,这时socket才可以发起新的连接。

简单说说4次挥手,3次挥手

既然上了张4次挥手的图,那得顺带说说吧。
为什么是4次挥手?
因为tcp是全双工的,有收,发两个通道,关闭一个通道需要2次,关闭两个就需要4次了。
客户端发出FIN包,客户端进入FIN-WAIT-1状态
服务器收到FIN包,服务器进入CLOSE-WAIT状态
剩下的状态看上面那个图吧,最后主动关闭socket的一方会进入TIME_WAIT,最终双方都CLOSE了,完成4次挥手。

既然说了4次挥手,3次握手也得顺带说说吧
为什么是3次握手?
首先完全可靠的通信并不存在

上一篇 下一篇

猜你喜欢

热点阅读