tcp状态介绍和解释

  转眼间,从事服务器后台开发,已经快三年了,最近想多总结些东西,先从最基本的开始写起吧!

  在公司经历了两个框架的开发和重构,其中一个点,就是把服务器内部通信的机制,从UDP转为TCP。

  先讲下TCP的基本应用,还有其中的各个状态的情况。

  以下的TCP的状态流程图:

  wKioL1Q6ojLA0L_mAAL_U7tM3DM896.jpg  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,重新建立连接,这时,之前在网络中传输的包,过一段时间,就可能被服务器接收到,

  而这个不是服务器期望接收到的。

  time_wait状态如何查看?

  通过 cat /proc/net/sockstat, 可以看到 time_wait的个数。

  time_wait状态过多,会有什么表现?

  time_wait过多,会占用系统的内存,当产生的个数超过 tcp_max_tw_buckets 这个值时,内核会

  不停的产生time_wait的日志,另外,tcpdump,也会抓到大量的rst包。通过netstat -s 查看,会

  发现 resets send out 这项数字会较快增长。


  服务器为什么会处于close_wait状态?

  服务器接收到客户端主动关闭的请求,但是自身还没执行主动关闭,就会处于close_wait状态。

  如果服务器在recv数据包的时候,可能fin没有接收到,tcp代为回复了ack包,这时就进入close_wait

  状态。

  如果服务器上面,绝大多数连接都处于close_wait状态,那么很可能是因为服务器本身接收并处理完

  客户端的数据,没有close连接导致的。


  rst的介绍?

  rst表示重置,用来异常的关闭连接。比如A和B两个服务模块,A已经关闭连接,而B不知道,如果B再试图往A发送数据时,则会收到rst的信号。

  通常情况下,rst是在收到的信息,不是期待中的信息时产生。


  实际应用中,有以上几种情况会收到rst的信号。

  1. 端口没有打开

  2. 请求超时

     比如跟服务器建立连接,服务器设置了套接字选项:SO_RECTIMEO,如果在建立连接的时候,超过了对应的时间,则服务器也会发送对应的信息,认为连接不可用;

  3. 提前关闭socket 



  本文内容,参考了

  unix网络编程卷一的内容 

  http://www.360doc.com/content/13/0702/10/1073512_297069771.shtml

  

你可能感兴趣的:(tcp,服务器,状态)