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又有什么意义呢?
为什么允许攒包一起发?
很合理, 如果我是流, 我就是没有"消息"的概念的, 我并不管你消息有没有发完, 我只在乎我要不要发, 我为了网络利用率, 那我确实可以攒着一起发, 反正我也只是发流中的一小段
Last updated
Was this helpful?