TCP协议

TCP

  • 1. 格式
  • 2. TCP原理
    • 2.1 确认应答(安全机制)
    • 2.2 超时重传(安全机制)
    • 2.3 连接管理机制(安全机制)
      • 2.3.1 三次握手
      • 2.3.2 四次挥手
    • 2.4 滑动窗口(效率机制)
  • 2.5 流量控制(效率机制)

1. 格式

TCP协议_第1张图片
源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
32位序号/32位确认号:后面详细讲;
4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60
6位标志位:
URG:紧急指针是否有效
ACK:确认号是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段

16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光包含TCP首部,也包含TCP数据部分

16位紧急指针:标识哪部分数据是紧急数据

2. TCP原理

TCP对数据传输提供的管控机制,主要体现在两个方面:安全和效率。
这些机制和多线程的设计原则类似:保证数据传输安全的前提下,尽可能的提高传输效率

2.1 确认应答(安全机制)

TCP协议_第2张图片

TCP将每个字节的数据都进行了编号。即为序列号
每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发

2.2 超时重传(安全机制)

TCP协议_第3张图片

主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;
如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发

2.3 连接管理机制(安全机制)

2.3.1 三次握手

TCP协议_第4张图片
TCP 要想保证可靠传输的前提就是网络通信是否通畅, "三次握手"机制就是用来验证网络通信是否通畅, 以及验证每个主机的发送能力和接收能力是否正常.
"三次握手"的每一步都有自己的用处:

  1. “第一次握手” 是用来验证客户端发送能力和服务器接收能力是否正常
  2. "第二次握手"是用来验证服务器的发送能力和客户端接受能力是否正常
  3. "第三次握手"是用来通知服务器服务器的发送能力和客户端接受能力是否正常

除此之外, 通信的时候也涉及到一些需要双方保持一致的参数也可以通过"三次握手"协商.

综上所述, "三次握手"的作用主要就是两方面:

  1. 验证通信路径是否通畅, 双方发送/接收能力是否正常.
  2. 协商必要参数, 使客户端和服务器使用相同的参数进行消息传输.

2.3.2 四次挥手

TCP协议_第5张图片
"四次挥手"的流程和"三次握手"非常相似, 经历过"四次挥手"之后连接就会断开, 双方就可以把各自保存的对方的信息的空间释放了.
网上很常见的一些面试题:
"四次挥手"可不可以三次完成?

"四次挥手"有的时候确实可以三次完成, 但是有的时候中间这两次不一定能合并.
因为 FIN 是通过应用程序的代码控制的, 而 ACK 是由内核控制的, 当收到 FIN 请求时会立刻返回 ACK, 但是由于程序可能没执行完所以不会立刻返回 FIN, 所以中间这两次不一定能合并.

如果服务器实在不发送 FIN 客户端连接就一直不会关闭吗?

当服务器接收到 FIN 请求就会转换成 CLOSE_WAIT 状态, 此时站在服务器的角度, 虽然连接没有关闭但是已经不能正常使用了. 如果缓冲区还有数据仍然可以正常读到但是如果进行写操作就会触发异常. 站在客户端角度, 如果经过一段时间的等待还是没有收到服务器的 FIN 请求就会单方面释放连接. 所以并不会一直不关闭.

如果通信过程中出现丢包怎么处理?

"三次握手"和"四次挥手"也带有重传机制, 会尽可能的重传, 如果连续多次重传失败就会单方面释放连接. 但是有一点需要注意的是: 最后一个 ACK 也有可能丢包, 所以当客户端发出去最后一个 ACK 时不能立即释放连接, 而是需要等待一段时间之后对方没有重传 FIN 才可以释放.(一般是等待网络是任意两点之间传输数据的最大时间 * 2)

2.4 滑动窗口(效率机制)

刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确认应答. 收到ACK后再发送下一个数据段. 这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候.
既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了).
TCP协议_第6张图片
和之前的方式不同, 滑动窗口是一次性发出一组数据, 在这一组数据发送的过程中不需要等待 ACK, 此时就相当于一份等待时间等四个 ACK.
一次发送数据的大小称为"窗口".
"窗口"越大批量发送的数据就越多, 效率就越高, 但是不能无限大, 那样就相当于完全不用等 ACK就和不可靠传输差不多了.

当然, 在数据传输的过程中也会发生"丢包"此时就会分为以下两种情况:

  1. 数据包丢失
    以上图为例: 当1001 - 2000 丢失之后 2001 - 3000 这个数据到达 B , B返回的 ACK 确认序号仍然是 1001 , 虽然 A 后续的数据都给 B 顺利传输过去了但是 B始终的会和 A 索要 1001 - 2000 这个数据, 当 A 连续几次都收到了 B 的索要请求就会知道该数据丢失了就会重传该数据. 当重传的 1001 到达 B 之后 B 返回的 ACK 就是 5001 了 1001 之后的数据不需要重传.
  2. ACK 丢失
    ACK 丢失并没有太大的影响, 因为当收到下一个确认序号时就表明之前的数据已经全部收到. 所以 除非所有的 ACK 都丢失, 如果只是丢一部分不会影响可靠传输.

2.5 流量控制(效率机制)

滑动窗口虽然能提高效率但是如果窗口太大就可能导致接收方或者传输中间的链路处理不过来就会产生丢包, 反而影响了效率. 流量控制就是给滑动窗口加个现在避免窗口太大导致接收方处理不过来.
因此, 流量控制就是根据接收方的处理能力来限制发送方的发送速度(窗口大小)
流量控制是根据接收缓冲区的剩余空间大小来作为衡量的指标
接收方在返回 ACK 报文时就会把接收缓冲区剩余大小反馈给发送方, 作为下一次发送数据窗口大小的参考依据.
TCP协议_第7张图片
当我们看的该数据只有 16 位时不免会感到疑惑, 这里大小只有 16 位是不是就代表窗口大小最大就是 16? 其实不然, 在选项中有一个选项, 是窗口大小扩展因子, 实际窗口大小是 16 位窗口大小 << 扩展因子, 此时就可以使能够表示的窗口大小就非常大了.

当接收缓冲区满了 A 会停止发送数据, 但是由于不知道多会有空闲空间, 所以就会周期性发送 “窗口探测包”(不会携带具体数据)只是为了触发 ACK(查询当前接收缓冲区情况), 当发现有空闲空间就会发送数据.
接收方可以通过窗口大小反向控制发送方传输数据.

你可能感兴趣的:(tcp/ip,网络,服务器)