1、流程状态图:
正常流程黑色部分。
fin位置1的tcp包,可以独立发送,也可以和其他数据包一起发送。
若需要重传的包中fin置为1,则连同fin包也要一起重传。例如:
发送方序列号: 接受方收到的包序列号: 10、11、12、13、14(fin) 10、11、13、14(fin) 这种情况,接受方回ack 确认序列号为12,发送方需要重发12、13、14(fin)包 |
接受方tcb收到最后的ack才会释放。
发送端调用close后,接受端调用recv返回0,进入close_wait状态。
ret = recv(fd); if (ret == 0) { close(); } |
2、思考问题:
1、出现大量close_wait状态的原因? 解决方案: |
2、如果主动方出现大量fin_wait_2,什么原因,如何解决? 1)先让对方处理。 2)无解,把进程kill掉。 3)出现一个fin_wait_2影响不大,再建立一个connect,可能出现大量fin_wait_2。 |
3、time_wait状态的作用
time_wait状态只有在超时之后才状态迁移至close状态。
1)预防被动方接受不到ack,被动方发送fin后,被动方启动定时器,等不到ack,再重传fin,此时主动方在time_wait状态,主动方的tcb没有释放,可以再次回复ack。
2)若没有time_wait状态,fin_wait_2状态后就close状态,即释放tcb,而被动方发送fin后,被动方启动定时器,等不到ack,再重传fin,主动方接受重传fin后,由于没有tcb,无法回应ack,导致被动方一直再last_ack状态,从而无法释放被动方的tcb。
SO_REUSEADDR会将timer_wait取消掉吗? 是将time_wait状态的tcb,主动方创建新socket时,拿来该tcb复用。 |
被动方发的fin,比被动方发的ack先到情况: 双方进入closing状态,等待对方回ack状态,和time_wait状态一样。 |
双方同时调用close函数: closing状态,双方同时调用close。 1)、fin_wait_1状态时接受到fin,变为closing状态。 2)、fin包先于ack包先到,变为closing状态。 双方都有time_wait状态。 |