TCP三次握手、四次挥手与状态转换

TCP为一个连接定义了11种状态,并且TCP规则规定了如何基于当前状态及在该状态下所接受的分节从一个状态装换到另一个状态。

三次握手

起初客户端与服务器TCP均除于CLOSED状态
建立一个TCP连接时会发生下述情况

  1. 服务器通常通过调用socket(), bind() , listen() 来准备接收外来的连接,称为被动打开,此时服务器状态由CLOSE->LISTEN
  2. 客户端通过connect() 发起主动打开。 状态由CLOSE->SYN_SNED。客户端的TCP发送一个SYN(同步)分节。它告诉服务器客户端将在连接中发送的数据的初始序列号。通常SYN不携带数据,其所在的IP数据报只含有一个IP首部、一个TCP首部、及可能有的TCP选项
  3. 服务器必须确认(ACK)客户的SYN,状态由LISTEN->SYN_REVD。同时自己发送一个SYN分节,它含有服务器将在同一连接中发送的数据的初始序列好。服务器在单个分节中发送SYN与ACK
  4. 客户端确认服务器的SYN
  5. 这就完成了三次握手建立了连接,之后的数据收发过程中服务器与客户端都处于ESTABLISHED状态

** ACK返回为接收到的SYN序列号+1

TCP三次握手

四次挥手

  1. 某一端调用close()。该端为主动关闭,状态由ESTABLISHED->FIN_WAIT_1。TCP发送一个FIN字节,表示数据发送完毕
  2. 另一端接收FIN执行被动关闭。状态由ESTABLISHED->CLOSE_WAIT。它将确认这个FIN并且它的接收也作为一个文件结束符传递给接收端的应用程序。这时候主动关闭端收到ACK状态由FIN_WAIT_1->FIN_WAIT_2.这时被动关闭端口还可以发送数据,主动关闭端不再发送数据
  3. 一段时间后接收到FIN的一端再次调用close()。状态由CLOSE_WAIT->LAST_ACK也发送一个FIN字节
  4. 执行主动关闭的一端确认这个FIN状态由FIN_WAIT_2->TIME_WAIT

这里写图片描述

 为什么要有TIME_WAIT?

当主动断开连接的一方(Initiator)发送FIN包给对方,且对方回复了ACK+FIN,然后Initiator回复了ACK后就进入TIME_WAIT状态,一直将持续2MSL后进入CLOSED状态。

那么,我们来看如果Initiator不进入TIME_WAIT状态而是直接进入CLOSED状态会有什么问题?

考虑这种情况,服务器运行在80端口,客户端使用的连接端口是12306,数据传输完毕后服务端主动关闭连接,但是没有进入TIME_WAIT,而是直接计入CLOSED了。这时,客户端又通过同样的端口12306与服务端建立了一个新的连接。假如上一个连接过程中网络出现了异常,导致了某个包重传并延时到达了服务端,这时服务端就无法区分这个包是上一个连接的还是这个连接的。所以,主动关闭连接一方要等待2MSL,然后才能CLOSE,保证连接中的IP包都要么传输完成,要么被丢弃了。

 TIME_WAIT带来的问题

系统中TIME_WAIT的连接数很多,会导致什么问题呢?这要分别针对客户端和服务器端来看的。

首先,如果是客户端发起了连接,传输完数据然后主动关闭了连接,这时这个连接在客户端就会处于TIMEWAIT状态,同时占用了一个本地端口。如果客户端使用短连接请求服务端的资源或者服务,客户端上将有大量的连接处于TIMEWAIT状态,占用大量的本地端口。最坏的情况就是,本地端口都被用光了,这时将无法再建立新的连接。

针对这种情况,对应的解决办法有2个:
1. 使用长连接,如果是http,可以使用keepalive
2. 增加本地端口可用的范围,比如Linux中调整内核参数:net.ipv4.ip_local_port_range

对于服务器而已,由于服务器是被动等待客户端建立连接的,因此即使服务器端有很多TIME_WAIT状态的连接,也不存在本地端口耗尽的问题。大量的TIME_WAIT的连接会导致如下问题:
1. 内存占用:因为每一个TCP连接都会有占用一些内存。
2. 在某些Linux版本上可能导致性能问题,因为数据包到达服务器的时候,内核需要知道数据包是属于哪个TCP连接的,在某些Linux版本上可能会遍历所有的TCP连接,所以大量TIME_WAIT的连接将导致性能问题。不过,现在的内核都对此进行了优化(待确认)。

那系统中处于TIME_WAIT状态的TCP连接数有上限吗?有的,这是通过net.ipv4.tcp_max_tw_buckets参数来控制的,默认值为180000。当超过了以后,系统就开始关闭这些连接,同时会在系统日志中打印日志。此时,可以将这个值调大一些,从这个参数的默认值就可以看出,对服务器而已,处于TIME_WAIT状态的TCP连接多点也没有什么关系,只是多占用些内存而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值