TCP协议以及TCP的三次握手和四次挥手

TCP 协议

按层次分,TCP 位于传输层,TCP 协议全称是(Transmission Control Protocol)传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议

TCP 协议特点

面向连接

使用 TCP 通信的双方必须先建立起连接,然后才能开始数据的读写。建立连接后双方的系统内核会为该连接分配必要的系统资源,用来管理连接的状态和传输在连接上的数据

可靠的

  • TCP 采用发送应答机制,即发送端发送的每个 TCP 报文段都必须得到接收方的应答后才认为 TCP 报文段传输成功。序号也保证了传送到接收端实体的包的按序接收
  • TCP 还具有超时重传机制,发送端在发出一个 TCP 报文段之后启动定时器,若在超时时间范围后还没收到接收端的应答信号,它将重发该数据报文。而 UDP 协议与 IP 协议一致,提供的是不可靠服务,数据确认和超时重传都需要在上层应用实现
  • TCP 报文段最终是以 IP 数据报发送的,IP 数据报到达接收端可能是重复/乱序的。所以 TCP 发送模块还会为每个包指定一个序号,TCP 接收模块对接收到的 TCP 报文段重排、整理,再交付应用程序

TCP 还提供流量控制和拥塞控制,防止过多的数据注入到网路中,缓解压力

单播和全双工

单播:每条 TCP 传输连接只能有两个端点,只能进行点对点(一对一)的单播数据传输,以基于广播和多播(目标是多个主机地址)的应用程序不能使用 TCP 服务

全双工:TCP 还是一个双向对称的全双工协议,一个 TCP 连接存在双向的读写通道,可以使数据在两个方向上同时进行传送操作,在发送数据的同时也能够接收数据,两者同步进行,就像平时打电话一样,说话的同时也能够听到对方的声音

半双工:是指一个虽然数据可以在一个信号载体的两个方向上传输,但是不能同时传输,时间段内只有一个动作发生

单工:是说数据传输是单向的,通信双方中,一方固定为发送端,一方则固定为接收端。信息只能沿一个方向传输

TCP 的三次握手

当一台计算机想要与另一台计算机通讯时,两台计算机之间的通信需要畅通且可靠,这样才能保证正确收发数据。为了准确无误地将数据送达目标处,TCP 协议采用了三次握手策略。用 TCP 协议把数据包送出去后,TCP 不会对传送后的情况置之不理,它一定会向对方确认是否成功送达

在这里插入图片描述

所谓三次握手,即建立 TCP 连接,就是指建立一个 TCP 连接时,需要客户端和服务端总共发送 3 个包以确认连接的建立。在 socket 编程中,这一过程由客户端执行 connect 来触发

在这里插入图片描述

  • 最开始客户端和服务器都是出于 closed 状态
  • 第一次握手:建立连接时,客户端发送 syn 包(syn=x)到服务器,并进入 SYN_SENT 状态,等待服务器确认。SYN:同步序列编号
  • 第二次握手:服务器收到 syn 包,必须确认客户的 SYNack=x+1),同时自己也发送一个 SYN 包(syn=y),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态
  • 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACKack=y+1),此包发送完毕,客户端和服务器进入 ESTABLISHEDTCP 连接成功)状态,完成三次握手
  • 若在握手过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包

简单的说,握手过程中主要使用了 TCP 的标志:SYNsynchronize) 和 ACKAcknowledgement)。发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYNACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表“三次握手”结束,TCP 连接成功。若在握手过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包

TCP 的四次挥手

四次挥手即终止 TCP 连接,就是指断开一个 TCP 连接,当一方完成它的数据发送任务后就能通过发送一个 FIN 来终止这个方向的连接,但是由于全双工机制,收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。TCP 全双工的每个方向都必须单独进行关闭,因此需要客户端和服务端总共发送 4 个包以确认连接的断开

在这里插入图片描述

  • 第一次挥手:客户端首先发送一个 FIN =1 ,seq = u(等于前面客户端已经传送的数据的最后一个字节的序号加 1TCP 规定,FIN 报文段即使不携带数据,也要消耗一个 seq 序号),用来表示关闭客户端到服务器的数据传送,客户端进入FIN_WAIT_1 状态
  • 第二次挥手:服务器收到 FIN 后,发送一个 ACK = 1 给客户端,ack = u+1,seq = V(等于前面服务器已经传送的数据的最后一个字节的序号加 1),此后服务器进入 CLOSE_WAIT 状态。客户端收到之后则进入 FIN-WAIT-2 状态,等待服务器进一步发送连接释放报文(在这之间还是需要接并处理受服务器发送的最后的数据)
  • 第三次挥手:服务器发送一个 FIN = 1,seq = w(在第二次和第三次挥手过程中服务器可能又发送了一些数据,因此假定为 N),ack = u+1TCP 规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号),ACK = 1,用来关闭服务器到客户端的数据传送,服务器进入 LAST_ACK 状态,等待客户端最后确认
  • 第四次挥手:客户端收到 FIN 后,接着发送一个 ACK = 1 给服务器,ack = w+1,seq = u+1,客户端进入 TIME_WAIT 状态,服务器在收到确认之后进入 CLOSED 状态,完成四次挥手
  • 客户端的 TIME_WAIT 状态会持续 2*MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有服务器的重发请求的话,客户端就进入 CLOSED 状态

TCP 总结

为什么建立连接是三次握手,而关闭连接却是四次挥手

因为当 Server 端收到 Client 端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,“你发的 FIN 报文我收到了”。只有等到我 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四步握手

为什么客户端最后要等待 2*MSL 时间

  • 保证客户端发送的最后一个 ACK 报文能够到达服务器,因为这个 ACK 报文可能丢失,站在服务器的角度看来,我已经发送了 FIN+ACK 报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个 2*MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启 2*MSL 计时器
  • 防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个 2*MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文

为什么不能用两次握手进行连接

3 次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机 SC 之间的通信,假定 CS 发送一个连接请求分组,S 收到了这个分组,并发送了确认应答分组。按照两次握手的协定,S 认为连接已经成功地建立了,可以开始发送数据分组。可是,CS 的应答分组在传输中被丢失的情况下,将不知道 S 是否已准备好,不知道 S 建立什么样的序列号,C 甚至怀疑 S 是否收到自己的连接请求分组。在这种情况下,C 认为连接还未建立成功,将忽略 S 发来的任何数据分组,只等待连接确认应答分组。而 S 在发出的分组超时后,重复发送同样的分组。这样就形成了死锁

如果已经建立了连接,但是客户端突然出现故障了怎么办

TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒钟发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接

猜你喜欢

转载自blog.csdn.net/weixin_38192427/article/details/114993689