流式协议

news/2025/2/21 18:09:09/文章来源:https://www.cnblogs.com/ydqblogs/p/18725720

搞清楚TCP流式协议的概念

  假设应用层通过TCP发送数据"HelloWorld",发送方可能分两次发送,比如"Hello"和"World",但是接收方可能一次就收到"HelloWorld!",或者有可能分多次收到,比如先收到"Hell",再收到"oWorld"。这说明TCP传输的数据是没有消息边界的,应用层需要自己处理这些数据的拆分和组合,这就是流式协议。故在应用层协议设计的时候需要考虑如何界定消息的结束,比如用特定的分隔符,或者固定长度,或者在消息头声明长度。例如HTTP协议中使用content-length或者分块传输编码。

为什么TCP要设计成流式协议呢?

  可以更灵活地处理数据,不需要维护消息边界,从而更高效地利用网络资源。比如,TCP可能会将多个小的数据包合并成一个大的数据包发送,或者将一个大的数据包拆分成多个小的数据包传输,这取决于网络状况和拥塞控制算法。这样的话,发送方和接收方的数据块可能不一致,所以应用层需要自己处理这些情况。

如何处理TCP这种流式协议呢?

  如果我们使用socket编程的时候,recv可能返回任意长度的数据,所以一般我们需要循环读取,并将每次读取的数据追加到缓冲区中,然后检查是否有完整的消息,处理完后再将剩余的数据保存在缓冲区中,供与下次读取的数据组合,解析成完整的数据消息。
另外,常见的粘包问题也是由于TCP的流式特性导致的。粘包是指多个应用层的数据包被合并成一个TCP段发送,或者一个应用层的数据包被拆分成多个TCP段。这时候,接收方可能一次读取到多个包的数据,或者需要多次读取才能得到一个完整的包。解决粘包问题的方法通常是在应用层添加消息边界,比如前面提到的长度前缀、分隔符或者使用自描述格式如JSON、XML等,但需要确保能够正确解析。
举个例子,比如客户端发送两个消息:"Hello"和"World",服务端可能先收到"HelloWorld",如果我们没有处理机制,此时我们是无法区分收到的这两个消息的,所以我们需要约定一种消息界定方法,比如,我们固定每次发送消息前,先发送4字节大小的长度信息,再发送实际内容,这样接收方先读取4字节的长度长度信息,解析出长度N,再去取接下来的N字节长度的消息内容,这样我们就可以处理流式协议了。
具体现实应用的例子就是HTTP协议,它使用Content-Length来制定正文的长度,甚至使用Transfer-Encoding: chunked来分块传输,每块前面有长度信息,这样接收方可以正确解析。

深刻理解TCP流式协议的关键点

1.流式协议的本质

  TCP是无消息边界的协议,数据就像水流一样连续传输。发送方多次写入的数据可能被接收方一次读取,反之亦然

1.发送端的多次send()调用可能被TCP合并为一个数据发送。
2.接收端的recv()调用可能返回任意长度的数据,无法保证与发送端发送的数据块一一对应。

2.设计流式协议的优点

灵活性:TCP根据网络状况进行动态调整数据包大小(MSS),合并小数据包(nagle算法)火拆分大数据报告,提升传输效率。
可靠性:通过序列号、确认应答、重传等机制保证数据按序到达,但无需维护应用层消息边界。

3.“粘包”与“拆包”问题

粘包:多个应用消息被合并为一个TCP报文接收
拆包:单个应用层消息被拆分为多个TCP报文传输

4.应用层处理TCP“粘包”的方案

  因为TCP不维护消息边界,应用层需要自行处理数据的组装和拆分。常见方案如下:

定义长度前缀:在消息头部定义固定字节的字段声明消息长度(HTTP的Content-Length)
分隔符:使用特许字符(如\r\n)标记消息结束(SMTP协议)。
自描述格式: Json/XML等格式通过语法标记边界,但需要解析器支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/887009.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SynchronousQueue底层实现原理剖

一、SynchronousQueue底层实现原理剖 SynchronousQueue(同步移交队列),队列长度为0。作用就是一个线程往队列放数据的时候,必须等待另一个线程从队列中取走数据。同样,从队列中取数据的时候,必须等待另一个线程往队列中放数据 二、SynchronousQueue用法 先看一个Synchron…

[2025.2.18 JavaWeb学习]Mybatis

入门MyBatis是一款优秀的持久层(dao)框架,用于简化JDBC的开发 使用:IDEA创建SpringBoot模块,而后勾选MySQL Driver和MyBatis Framework pom.xml引入了mybatis-spring-boot-starter起步依赖、com.mysql依赖包、org.springframework.boot单元测试依赖 pojo中,创建实体对象,…

ROS2-PX4学习笔记

搞点小研究,欢迎对ROS2、PX4感兴趣的同学浏览。希望Mujica能好起来。ROS2-PX4学习笔记 前言 做毕设其实是个有点痛苦的过程。 毕竟所有东西都得现学,然后探索,时间又有限。 研究没接触过的新东西,总会失败,没有产出,搞久了人难受。 所以还是写一点东西吧。 我挺想把这个坑…

MessagePipe 中文文档

MessagePipe 是一个专为 .NET 和 Unity 设计的高性能内存/分布式消息管道。支持所有 Pub/Sub 场景、CQRS 中介模式、Prism 的 EventAggregator(视图与视图模型解耦)、IPC(进程间通信)-RPC 等。MessagePipeMessagePipe 是一个专为 .NET 和 Unity 设计的高性能内存/分布式消息…

Avalonia系列文章之样式与主题

随着社会的发展,大家对软件的要求,从最初的命令行输入输出,到可视化输入输出,如报表,图表等;从最初的可用性,稳定性为主,到现代软件理念中的便捷易用性转变,在保证稳定可用外,对软件的交互易用要求越来越高,而这些则离不开UI设计以及样式的应用。今天以一些简单的小…

SynchronousQueue的put方法底层源码

一、SynchronousQueue的put方法底层源码 SynchronousQueue 的 put 方法用于将元素插入队列。由于 SynchronousQueue 没有实际的存储空间,put 方法会阻塞,直到有消费者线程调用 take 方法移除元素 1、put 方法的作用将元素插入队列。如果没有消费者线程等待,当前线程会阻塞,…

【Tomcat文件上传】绕WAF姿势深入研究

环境 本地环境tomcat8.5.93,无黑白名单限制getSubmittedFileName()函数 tomcat可以通过filePart.getSubmittedFileName();获取上传文件的原始名filename获取Content-Disposition头后,判断值是否form-data或attachment开头 然后112行将form-data; name="file"; file…

关于一个手机控制电脑执行特定任务的解决方案探索【1】

【前言】 说来话长,关于这个手机控制电脑执行特定任务的想法早在几年前就有,但因为对安卓平台开发经验实在不足,就一直拖到了现在。不过好在没有忘记初衷,接下来我们一起来看我的思路和方法。 【思路】 想要通过手机作为控制端,来发送指令给同一网络下的电脑端,执行特定任…

如何升级 PowerShell 到最新版本

前言最近,需要大量使用PowerShell,然后有需要PowerShell 7正文升级的步骤也比较简单,按照下面的步骤就好了文字版本的,方便大家复制粘贴。PS C:\WINDOWS\system32> $PSVersionTable.PSVersionMajor Minor Build Revision ----- ----- ----- -------- 5 1 …

百万架构师第四十课:RabbitMq:RabbitMq-工作模型与JAVA编程|JavaGuide

来源:https://javaguide.net RabbitMQ 1-工作模型与Java编程 课前准备 预习资料 Windows安装步骤 Linux安装步骤 官网文章中文翻译系列 环境说明 操作系统:CentOS 7 JDK:1.8 Erlang:19.0.4或最新版 RabbitMQ:3.6.12或最新版 版本对应关系 典型应用场景跨系统的异步通信。人…

1月16日java假期学习读书笔记

一、学习目标 掌握HTML的基本结构和常用标签。 了解CSS的基本选择器和样式规则。 通过实际代码练习,构建一个简单的网页。 二、学习内容 (一)HTML基础 HTML简介 HTML(HyperText Markup Language,超文本标记语言)是用于构建网页的标准标记语言。 它通过一系列的标签(如、…

MapStruct使用指南并结合Lombok

MapStruct使用指南并结合Lombokhttps://juejin.cn/post/6956190395319451679#heading-1 2024-01-11 18:34:06如何结合 lombok 也就说说如果代码中使用了 lombok 注解来生成代码,mapstruct 的 getter/setter 方法也使用了 lombok 的 api,那就需要额外的配置,因为这两个工具都是使…