赞
踩
TCP 是面向连接的、可靠的字节流协议。因此,在传输数据之前通信双方必须建立一个 TCP 连接,建立 TCP 连接需要在服务器和客户端之间进行三次握手。通信双方数据传输完毕之后进行连接释放,释放连接需要在通信双方之间进行四次挥手。
TCP 所谓的“连接”,只是通信双方维护一个“连接状态”,让它看上去好像有连接一样,其实 TCP 连接是虚拟的连接,不是电路连接。首先看下 TCP 的状态机,状态机是 TCP 连接与释放的全过程。如下图所示:
下面针对 TCP 状态机所出现的各个状态进行简要的分析:
TCP 连接的正常建立过程通信双方需要三次握手,其过程如下图所示:
TCP 协议提供可靠的连接服务,采用有保障的三次握手方式来创建一个 TCP 连接。三次握手的具体过程如下:
正常情况下,通信一方请求建立连接,另一方响应该请求,但是如果出现,通信双方同时请求建立连接时,则连接建立过程并不是三次握手过程,而且这种情况的连接也只有一条,并不会建立两条连接。同时打开连接时,两边几乎同时发送 SYN,并进入 SYN_SENT 状态,当每一端收到 SYN 时,状态变为 SYN_RCVD,同时双方都再发 SYN 和 ACK 作为对收到的 SYN 进行确认应答。当双方都收到 SYN 及相应的 ACK 时,状态变为 ESTABLISHED。其过程入下:
由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。原则是主动关闭的一方发送一个 FIN 报文来表示终止这个方向的连接,收到一个 FIN 意味着这个方向不再有数据流动,但另一个方向仍能继续发送数据,直到另一个方向也发送 FIN 报文。TCP 连接释放的过程如下图所示:
以下是释放连接的四次挥手过程:
正常情况下,通信一方请求连接关闭,另一方响应连接关闭请求,并且被动关闭连接。但是若出现同时关闭连接请求时,通信双方均从 ESTABLISHED 状态转换为 FIN_WAIT_1 状态。任意一方收到对方发来的 FIN 报文段后,其状态均由 FIN_WAIT_1转变到 CLOSING 状态,并发送最后的 ACK 数据段。当收到最后的 ACK 数据段后,状态转变化 TIME_WAIT,在等待 2MSL 时间后进入到 CLOSED 状态,最终释放整个 TCP 传输连接。其过程入下:
因为当处于 LISTEN 状态的服务器端收到来自客户端的 SYN 报文(客户端希望新建一个TCP连接)时,它可以把 ACK (确认应答)和 SYN (同步序号)放在同一个报文里来发送给客户端。但在关闭 TCP 连接时,当收到对方的 FIN 报文时,对方仅仅表示对方已经没有数据发送给你了,但是你自己可能还有数据需要发送给对方,则等你发送完剩余的数据给对方之后,再发送 FIN 报文给对方来表示你数据已经发送完毕,并请求关闭连接,所以通常情况下,这里的 ACK 报文和 FIN 报文都是分开发送的。
为什么一定要进行三次握手?
当客户端向服务器端发送一个连接请求时,由于某种原因长时间驻留在网络节点中,无法达到服务器端,由于 TCP 的超时重传机制,当客户端在特定的时间内没有收到服务器端的确认应答信息,则会重新向服务器端发送连接请求,且该链接请求得到服务器端的响应并正常建立连接,进而传输数据,当数据传输完毕,并释放了此次 TCP 连接。若此时第一次发送的连接请求报文段延迟了一段时间后,到达了服务器端,本来这是一个早已失效的报文段,但是服务器端收到该链接请求后误以为客户端又发出了一次新的连接请求,于是服务器端向客户端发出确认应答报文段,并同意建立连接。如果没有采用三次握手建立连接,由于服务器端发送了确认应答信息,则表示新的连接已成功建立,但是客户端此时并没有向服务器端发出任何连接请求,因此客户端忽略服务器端的确认应答报文,更不会向服务器端传输数据。而服务器端却认为新的连接已经建立了,并在一直等待客户端发送数据,这样服务器端一直处于等待接收数据,直到超出计数器的设定值,则认为客户端出现异常,并且关闭这个连接。在这个等待的过程中,浪费服务器的资源。如果采用三次握手,客户端就不会向服务端发出确认应答信息,服务器端由于没有收到客户端的确认应答信息,从而判定客户端并没有请求建立连接,从而不建立该连接。
为什么需要在 TIME_WAIT 状态必须等待 2MSL 时间,而不直接给进入 CLOSED 状态?
主要有两个原因:
参考资料:
《TCP/IP 详解》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。