xiaohanliang
Network
Network
  • hi
  • LOWER
    • 0. arp决定下一跳
    • 1. dns决定终点
    • 2. [WIP]dns是不是真的有这些层级
  • MIDDLE
    • 0. 如何理解tcp握手的设计
    • 1. 诡异的tcp拆包现象
    • 2. tcp是一种高效的协议吗
    • 3. 为什么说没有人可以裸用tcp
    • 4. 尝试理解tcp的设计
    • 5. 连接建立@tcp调优
    • 6. 连接断开@tcp调优
    • 7. [WIP]拥塞控制@tcp调优
    • 8. 不需要这些花里胡哨的东西
    • 9. 怎么又是socket又是tcp
  • UPPER
    • 0. 为什么大家都用http
    • 1. [WIP]为什么http也keep-alive
    • 2. 如何保证pipeline的顺序到达
    • 3. 如何保证http的安全性
    • 4. 只不过https基于tls连接
    • 5. 怎么理解get/post
    • 6. http2为什么更快
    • 7. [WIP]内置加速的http3
    • 8. 怎样制造出实时效果-ws
    • 9. kcp是如何榨干你的带宽的
  • DEVICES
    • [302] 跳转到Linux网络设备
  • KUBERNETES NETWORK
    • [302] 跳转到容器网络
Powered by GitBook
On this page
  • 不是包, 不谈包
  • TCP的信息流概念
  • 为什么SEQ这么重要
  • 为什么没有size字段
  • 为什么允许攒包一起发?

Was this helpful?

  1. MIDDLE

4. 尝试理解tcp的设计

不是包, 不谈包

我们打开wireshark能看到的TCP包都是仅仅有条的, 一个接着接着一个清晰明朗的. 这容易让人误以为一个包就是一条消息, 跟UDP一个路数来着. 其实这是wireshark为了方便你阅读帮助你把消息整理了一遍的效果. 我很长一段时间认为TCP跟UDP唯一的区别就是一个可靠一个不可靠而已.

反正大家都是发包嘛. 如果我们换一个角度去思考. UDP才是真正的一个包一条消息. TCP的确也发包, 但是TCP一个包只是消息流中的一小段. 你如果站在这个角度上去想, 突然很多设计的点变的很合理:

  • 为什么TCP握手的时候交换的是SEQ, 为什么每次ACK都是认可SEQ, 为什么ACK后面的,前面的就默认是都收到了?

  • 为什么TCP就是没有长度字段?

  • 为什么TCP允许积攒一些小包合并成一个大包一起发送?

TCP的信息流概念

TCP消息本身没有消息长度概念, TCP搞的是信息流, 也就是希望你从流中一个字节一个字节的读出信息, 然后重新拼出你想要的结构体来. 流本身是没有边界的, 流没有开始与结束, 只有一大堆字节等你来拼. 因此我们没有包长度, 我们只有SEQ字段, 表示流的最新位置

从这个角度上想, MSS与MTU的作用TCP包会被拆成小包, Nagel算法将小包又合并成大包. 就变得可以理解了.

为什么SEQ这么重要

SEQ如此重要以至于SEQ已经位于握手要做的第一件事了. 我们把SEQ想象成字节流中的位置,

  • 那么握手的时候就等于说告诉对方, 我的字节流要从这里开始, 你就把这个当成起点, 从这里开始往下读把.

  • 那么响应ACK包中的x+1就代表, 你好你的字节流我已经读到这里了, 请你接着发, 我好接着从字节流中往外读

为什么没有size字段

因为TCP的每个包只传送字节流中的一个小段, 这个小段可能不包含一个完整的MySQL信息, 可能拼凑了好几个消息, 我就算都给你了你也不一定需要, 因为某个包我可能只发了一半过来, 剩下一半下次给你, 既然这样, 我告诉你size又有什么意义呢?

为什么允许攒包一起发?

很合理, 如果我是流, 我就是没有"消息"的概念的, 我并不管你消息有没有发完, 我只在乎我要不要发, 我为了网络利用率, 那我确实可以攒着一起发, 反正我也只是发流中的一小段

Previous3. 为什么说没有人可以裸用tcpNext5. 连接建立@tcp调优

Last updated 4 years ago

Was this helpful?