标签:服务器 状态 time_wait.close_wait tcp
转眼间,从事服务器后台开发,已经快三年了,最近想多总结些东西,先从最基本的开始写起吧!
在公司经历了两个框架的开发和重构,其中一个点,就是把服务器内部通信的机制,从UDP转为TCP。
先讲下TCP的基本应用,还有其中的各个状态的情况。
以下的TCP的状态流程图:
服务端:socket bind listen accept read write close
客户端:socket connect write read close
其中,状态的变化主要有:
syn_sent syn_rcvd established fin_wait_1 fin_wait_2 close_wait time_wait last_ack
close 等各种状态。
tcp的建立和释放,简单说,就是三次握手和四次释放。
三次握手的过程如下:
1. 服务器调用socket,bind,listen,完成被动打开的过程,进入listen的状态;
2. 客户端调用 connect 主动打开,向服务器发送syn1,进入syn_sent的状态;
3. 服务器确认客户端的syn,同时自己发送一个syn2和ack,对客户端进行确认,进入syn_rcvd状态;
4. 客户端接受到服务器发送的确认信息,进入establish状态,对服务器发送ack,服务器接受到ack,也进入到establish状态。
这个过程中的包,通过tcpdump,抓取tcp连接的包时,经常就可以收到。
四次释放的过程如下:
1. 主动关闭的一方,调用close,发送fin M,表示不再发送数据,进入fin_wait_1状态;
2. 被动关闭的一方,接收到fin M,进入close_wait状态,发送ack M+1;
3. 主动关闭的一方,接收到 ack M+1,进入 fin_wait_2 状态;
3. 被动关闭的一方,发送fin N,进入last_ack状态;
4. 主动关闭的一方,接收到fin N, 进入time_wait状态,发送ack N+1, 被动关闭的一方接收到
ack,进入 closed状态
特殊的情况,是主动关闭的一方,发送fin M,没有接收到ack M+1,而是接收到 fin N, 表示对方
也是要马上关闭数据,所以,马上转入closed状态。
tcp的释放,为什么需要四次握手?
如果一方执行主动关闭,只能保证本方不再发送数据,但是,无法确定是否要继续接收数据;
为什么需要time_wait状态?
1. 可靠地实现TCP全双工连接的终止
网络数据的传输,肯定要考虑丢包的情况,如果最后一次ack丢失,被动关闭的一方,将重新发送
它的FIN,因此主动关闭的一方,必须维持状态,允许自身重新发送最终的ACK。
2. 允许老的重复分节在网络中消逝
time_wait状态保持2msl的时间,msl指的是网络包在网络中存活的最长时间。
假设没有time_wait状态,客户端A向服务器B发送数据,并进入closed状态。过一段时间,又用原来
的端口和IP,重新建立连接,这时,之前在网络中传输的包,过一段时间,就可能被服务器接收到,
而这个不是服务器期望接收到的。
服务器为什么会处于close_wait状态?
服务器接收到客户端主动关闭的请求,但是自身还没执行主动关闭,就会处于close_wait状态。
如果服务器在recv数据包的时候,可能fin没有接收到,tcp代为回复了ack包,这时就进入close_wait
状态。
如果服务器上面,绝大多数连接都处于close_wait状态,那么很可能是因为服务器本身接收并处理完
客户端的数据,没有close连接导致的。
本文内容,参考了
unix网络编程卷一的内容
本文出自 “思考沉淀” 博客,请务必保留此出处http://joezhengjinhong.blog.51cto.com/7791846/1563070
标签:服务器 状态 time_wait.close_wait tcp
原文地址:http://joezhengjinhong.blog.51cto.com/7791846/1563070