TCP

TCP,Transmission Control Protocol 传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。通俗来讲,TCP就是双方通信的一个规范标准,负责对数据的传输进行一定的控制。TCP 报文格式如下:

现对其中的结构做个简单介绍

  • 源端口号就是指本地端口,目的端口号就是远程端口

  • 序号,也称序列号(Sequence Number),用于 TCP 通信过程中某一传输方向上字节流的每个字节的编号,以防止乱序问题。简单来说,就是在传输过程中用序列号来标记自己的位置,保证数据能按序传输

  • 确认序号,也称确认序列号(Acknowledgment Numbe),是接收确认端所期望收到的下一序列号。确认序号应当是上次已成功收到数据字节序号加 1,只有当标志位中的 ACK 标志为 1 时该确认序列号的字段才有效。主要用来解决不丢包的问题

  • 标志位,TCP Flag,TCP 首部中有 6 个标志比特,它们中的多个可同时被设置为 1,主要是用于操控 TCP 的状态机,依次为 URG,ACK,PSH,RST,SYN,FIN

    • ACK

      表示应答域有效,这个标识可以理解为发送端发送数据到接收端,发送的时候 ACK 为 0,标识接收端还未应答,一旦接收端接收数据之后,就将 ACK 置为 1,发送端接收到之后,就知道了接收端已经接收了数据

    • SYN

      表示同步序列号,用来建立 TCP 连接。SYN 标志位和 ACK 标志位搭配使用,当连接请求的时候,SYN = 1,ACK = 0;连接被响应的时候,SYN = 1,ACK = 1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有 SYN 的数据包,如果对方主机响应了一个数据包回来 ,就表明这台主机存在这个端口

    • FIN

      表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送 FIN 标志位的 TCP 数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描

  • 窗口大小(Window Size),也称为滑动窗口大小,用来进行流量控制


TCP 三次握手

TCP 三次握手,即建立 TCP 连接,需要客户端和服务端总共发送 3 个包以确认连接的建立。在 Socket 编程中,这一过程由客户端执行 connect 来触发。TCP 握手的目的有三个:确认双方的接收与发送能力是否正常;初始化序列号,为后面的可靠传送做准备;进行数字证书的验证以及加密密钥的生成

  • 第一次握手:客户端发送请求报文将 SYN = 1 同步序列号和初始化序列号 seq = J 发送给服务端,发送完之后客户端处于发送等待状态
  • 第二次握手:服务端受到 SYN 请求报文之后,如果同意连接,会以自己的同步序列号 SYN = 1、初始化序列号 seq = K 和确认序列号(期望下次收到的数据包)ack = J + 1 以及确认号 ACK = 1 报文作为应答,此时服务器为确认接收状态
  • 第三次握手:客户端接收到服务端的 SYN + ACK 之后,知道可以发送下一序列的数据包了,然后发送同步序列号 ack = K + 1 和数据包的序列号 seq = J + 1 以及确认号 ACK = 1 确认包作为应答,客户端转为确认连接状态

为什么是三次握手?

为什么是三次握手,而不是一次、二次呢?因为有可能出现这种情况:客户端发送了一个连接请求,但出现网络延迟,导致客户端没有及时收到服务端的响应,就会认为本次请求失效。而这时原本延迟的请求又来到服务端,服务端确认并保持等待状态,但实际上此时客户端并没有与服务端连接的意思,这就会导致服务器一直处于等待状态,造成资源浪费


TCP 四次挥手

TCP 四次挥手,即终止 TCP 连接,需要客户端和服务端总共发送 4 个包以确认连接的断开。在 Socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发

  • 第一次分手:第一次分手无论是客户端还是服务端都可以发起,因为 TCP 是全双工的。假如客户端发送的数据已经发送完毕,发送 FIN = 1 告诉服务端,客户端所有数据已经全发完了,服务端可以关闭接收了,但如果服务端还有数据要发给客户端,客户端照样可以接收的。此时客户端处于 FIN_WAIT_1 等待关闭状态
  • 第二次分手:服务端接收到客户端的释放请求连接之后,知道客户端没有数据要发给自己了,然后服务端发送 ACK = 1 告诉客户端已经收到发给自己的信息,此时服务端处于 CLOSE_WAIT 等待关闭状态
  • 第三次分手:此时服务端已经没有数据向客户端发送了,然后发送一个 FIN = 1,用于告诉客户端,服务端的所有数据发送完毕,客户端可以关闭接收数据连接了。此时服务端状态处于 LAST_ACK 确认关闭状态
  • 第四次分手:此时如果客户端收到了服务端发送完的信息之后,就发送 ACK = 1,告诉服务端,客户端已经收到了服务端的信息,服务端处于 CLOSED 状态,四次挥手全部完成

为什么是四次挥手?

为什么是四次挥手呢?因为关闭连接时,己方收到对方的 FIN 报文,仅仅表示对方不再向自己发送数据,但还能接受数据。己方可能还有数据要发送给对方,所以不能向三次握手一样直接把 ACK 和 SYN 放一起发送,而是先发送 ACK,直到没有数据要发送了,才是 FIN 确认关闭连接


为什么 TIME_WAIT 状态需要经过 2MSL 才能返回到 CLOSE 状态?

假设出现各种网络原因,使得服务端没有接收到客户端最后回复的 ACK,这时服务端就会重新发送 FIN。如果没有 2MSL 的延迟,那客户端回复 ACK 后就立即处于 close 状态,自然也无法接收到服务端再次发送的 FIN。最后服务端会认为出现连接错误问题并报告给上层。这种情况虽然不至于导致数据丢失,但不符合 TCP 是可靠连接的要求


内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/Yee-Q/p/13796374.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!