为什么TCP要做成流式协议,而非包呢?

简介: 为什么TCP要做成流式协议,而非包呢?

0 今日话题

为什么TCP要做成流式协议,而非包呢?


哦莫西多 。 先假设TCP做成“包式协议 “的ROI,再探讨可⾏性。先要澄清,作为传输层协议,实际上有对上和对下两套抽象。


1 对下

即⽹络层,⼀般是IP协议,再下就是⽹络层如以太⽹协议 。


TCP对下层的抽象从第⼀天开始就是包。TCP失败重传、拥塞控制、流量控制等机制都建⽴在“TCP packet”前提下。


对以太⽹MTU这类问题,可假设TCP对下总是能处理好,⽽不会因为某个包太⼤就傻乎乎丢数据。因此不过多讨论。


2 向上

所以,题目中的"包"只能是面向上层或说是"面向用户的包”。可简单理解为类似把HTTP1.0里的request/response (或叫message) 的设计直接放到TCP直接实现。这样发送方就很方便写入一个应用的"包",读取方就能读取整个这样一个应用的包。


对一般的需求看上去很合适。并且看起来这个设计也不会太破坏TCP对下层的抽象。只要在发送和接收buffer里增加标记每个用户包的开始、结束位置,到了地方就给上层recv返回即可。


3 有麻烦了

但这样有问题:必须给这个包设计⼀个最⼤⼤⼩,否则TCP不知道要分配多⼤内存。若⽤户包>接收buffer,很难设计⼀个合理接⼝⾏为,因为这时recv:

  • 是返回⼀部分数据
  • 还是返回错误?
  • 还是必须逼发送⽅⼿⼯拆包?
  • ⼜或⼀个上层应⽤在启动时要告诉TCP⾃⼰需要有多⼤的包。但上层应⽤可能并不能提前知道到底⼀个包多⼤

如上层要上传⼀个⽂件,⽂件多⼤⽆法提前知晓。所以,为了可⽤,上层必然根据⾃⼰的业务需求⼀定要实现⼀个⾃⼰拆包的协议。⽽⼀旦上层实现了这协议,那TCP层拆包就完全丧失意义。

3.1 UDP咋做的?

UDP就是定义最⼤的包⼤⼩。因此使⽤UDP的应⽤层⼀般会设计为“绝对不会超 过这个⼤⼩”;或者如果要超了就改成TCP。⼀个典型的例⼦就是DNS的协议设计。这种形式应 付⼀下简单的场景还凑合,但对于⼀般业务开发是绝对不可接受的。


⽽某些应⽤场景,⾃身就是数据流。若TCP设计为⾯向⽤户包,这些场景就须引⼊“流转包 ”。技术上也可⾏。或者TCP同时提供⾯向包、⾯向流两种语义,TCP需要定义“包连接”和“流连接”两种连接,各传各?这⼤⼤增加协议设计和使⽤复杂度。


更郁闷的,若业务场景需要进⾏有序数据传输,开头是个包,包完了是流,⼜咋处理?对应⽤层协议还好,可针对场景定制设计;问题是TCP定位是通⽤传输协议,若搞这种定制设计就没法⽤。


4 包拆分

更麻烦其实是不同应⽤场景,包拆分机制不⼀。常⻅⽅式提供⼀个字段明确标记包的字节数。


有的根据请求中的特殊字符区分是否要拆包。⽽特殊字符⼜涉及编码和escape之类问题。⽽这些字节流⼜可能被加密,得到结果还跟密钥相关。这些数据到TCP这⾥就就没法搞了。


合理做法还是应⽤层先拆,拆好了加密,加完密再传输。

5 应⽤层拆包

因此发现,⽆论TCP层咋折腾,都不太可能绕开“应⽤层拆包 ”。所以,也许更好处理⽅式:完全⼲掉“流式协议”这层的抽象,但保留底层包的保序/重传/流控/拥塞控制等机制⸺QUIC就是这样。但对⼏⼗年前的⽹络协议设计,TCP流式协议是⾜够好选择。在众多协议下能活下来并得到⼴泛应⽤⾜以证明。


6 总结

BTW,的确存在⽀持message的传输层协议SCTP,但过于复杂得不到⼴泛⽀持(Windows压根不⽀持),濒临灭绝。


⽽那些适合⽤“⽤户包”来实现的功能(如微服务的RPC ),可直接⽤HTTP做传输层。即把⼀个本设计为应⽤层的协议,保留其Header,编码,拆包等基本能⼒;同时将如Cache协商,⽤不到的编码格式等扔掉不实现。在不对基础协议做更改的前提下就能run。


另外⼀个选项⽤ZeroMQ,天然封装Req/Resp能⼒,可在此基础构造应⽤层协议。钱多⼤⼚,⾃⼰手写协议满足业务也完全可。

————————————————

版权声明:本文为CSDN博主「JavaEdge.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_33589510/article/details/133660870

目录
相关文章
|
5月前
|
缓存 网络协议 安全
你以为你了解TCP协议?这些你可能不知道的细节才是关键!
【6月更文挑战第1天】 这篇文章探讨了TCP协议的深入细节,包括SYN/FIN包为何消耗序列号以确保连接可靠性,半连接队列和SYN Flood攻击的概念及其防御策略。此外,文章还介绍了TCP Fast Open(TFO)技术,它通过减少握手次数提升连接速度和安全性。最后,文章讨论了TCP时间戳的作用,它用于精确计算往返时延和防止序列号回绕问题。通过理解这些概念,读者能更好地掌握TCP协议并应对相关面试。
你以为你了解TCP协议?这些你可能不知道的细节才是关键!
|
6月前
|
缓存 网络协议 NoSQL
基于UDP的可靠性传输协议-KCP简介
基于UDP的可靠性传输协议-KCP简介
215 0
|
5月前
|
网络协议 IDE 开发工具
TCP通信协议及代码细节
TCP通信协议及代码细节
35 0
|
6月前
|
Web App开发 网络协议 测试技术
|
6月前
|
网络协议 Java 数据安全/隐私保护
如何使用Java实现基于TCP/IP协议的即时通讯系统
TCP/IP协议是现代计算机网络通信中最常用的协议之一,而即时通讯系统则是当前互联网应用中非常普遍的一种场景。本文将介绍如何使用Java编程语言来实现基于TCP/IP协议的即时通讯系统,包括建立服务端和客户端、发送和接收消息等方面的详细步骤和示例。
|
6月前
|
安全 网络协议 网络安全
给女朋友解释为什么TCP可靠而非安全,UDP非可靠而安全(聊天记录)
给女朋友解释为什么TCP可靠而非安全,UDP非可靠而安全(聊天记录)
75 0
|
网络协议 Java
java实现TCP数据传输反馈
java实现TCP数据传输反馈
|
存储 网络协议 程序员
【TCP 协议】报文格式,数据可靠传输的机制(一)
【TCP 协议】报文格式,数据可靠传输的机制(一)
289 0
|
网络协议 网络性能优化 网络安全
网络-UDP协议详解(代码、实战)
网络-UDP协议详解(代码、实战)
762 0
网络-UDP协议详解(代码、实战)
|
Web App开发 网络协议 测试技术
接口协议之抓包分析 TCP 协议
接口协议之抓包分析 TCP 协议