为什么TCP是面向字节流协议

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。

笔者在TCP 机制一文中有说到 TCP 是面向字节流的,这篇博客给大家介绍一下:为什么 TCP 是面向字节流协议的。

首先说一下 UDP ,是一个面向报文的协议,当用户消息通过 UDP 协议传输时,操作系统不会对消息进行拆分,在组装好 UDP 头部后就交给网络层来处理,所以发出去的 UDP 报文中的数据部分就是完整的用户消息,也就是每个 UDP 报文就是一个用户消息的边界,这样接收方在接收到 UDP 报文后,读一个 UDP 报文就能读取到完整的用户消息。

如果收到了两个 UDP 报文,那么 UDP 是如何将这些消息进行区分的?

如图所示:UDP 底层维护了一个队列,通过对队列进行消费
在这里插入图片描述

那么,为什么 TCP 是面向字节流

当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。这时,接收方的程序如果不知道发送方发送的消息的长度,也就是不知道消息的边界时,是无法读出一个有效的用户消息的,因为用户消息被拆分成多个 TCP 报文后,并不能像 UDP 那样,一个 UDP 报文就能代表一个完整的用户消息。

例如:发送方准备发送 hello 和 world 这两个消息,在发送端,当我们调用 send 函数完成数据 “发送” 以后,数据并没有被真正从网络上发送出去,只是从应用程序拷贝到了操作系统内核协议栈中。至于什么时候真正被发送,取决于发送窗口、拥塞窗口以及当前发送缓冲区的大小等条件。也就是说,我们不能认为每次 send 调用发送的数据,都会作为一个整体完整地消息被发送出去。所以发送 hello + world 信息,如果没有分界,会出现 hel + loworld,又或者 hell + oword等。

我们不知道 hello 和 world 这两个用户消息是如何进行 TCP 分组传输的。
因此,我们不能认为一个用户消息对应一个 TCP 报文,正因为这样,所以 TCP 是面向字节流的协议。

当两个消息的某个部分内容被分到同一个 TCP 报文时,就是我们常说的 TCP 粘包问题,这时接收方不知道消息的边界的话,是无法读出有效的消息。

要解决这个问题,要交给应用程序。

如何解决粘包

一般有三种方式分包的方式:

  1. 固定长度的消息:
    比如规定一个消息的长度是 64 个字节,当接收方接满 64 个字节,就认为这个内容是一个完整且有效的消息。但是这种方式灵活性不高,实际中很少用

  2. 特殊字符作为边界:
    如果报文中就有特殊字符,那么系统很有可能将消息中的特殊字符当成分界点,刚好消息内容里有这个特殊字符,我们要对这个字符转义,避免被接收方当作消息的边界点而解析到无效的数据。
    在这里插入图片描述

  3. 自定义消息结构:
    可以自定义一个消息结构,由包头和数据组成,其中包头包是固定大小的,而且包头里有一个字段来说明紧随其后的数据有多大。当接收方接收到包头的大小(比如 4 个字节)后,就解析包头的内容,于是就可以知道数据的长度,然后接下来就继续读取数据,直到读满数据的长度,就可以组装成一个完整到用户消息来处理了。

总结

所以 TCP 是面向字节流的协议,在消息体传输的过程中,是分段进行的,而 UDP 则是面向报文的传输协议,一次发送一个报文,用一个队列来维护。

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

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

相关文章

使用python将32位的bmp转成24位的

前言 一个临时需求,要将32位的bmp图像转成24位的 代码 使用opencv读取图片,然后重新存一下就可以。我看有些博主就这个内容还设置了收费,也不害臊。 import cv2if __name__ "__main__":img cv2.imread("IMG-0001-00001.…

目标跟踪基础:数据关联算法

本文来自公众号“AI大道理” —————— 数据关联是多目标跟踪任务中的关键步骤,其目的主要是为了进行帧与帧之间的多个目标的匹配。 1、数据关联 数据关联其实就是一个沿着时间轴,将来自同一个物体的不同时刻的信号串联起来的过程。 数据关联通常在…

桥接(Bridge)模式

目录 动机使用场景参与者优劣协作实现相关模式应用和思考 桥接模式是将抽象部分和它的实现部分分离,使他们都可以独立的变化的对象结构型模式。桥接模式通过将继承改为组合的方式来解决问题;具体来说就是抽取其中一个维度并使之成为独立的类层次。 动机…

开源堡垒机Guacamole二次开发记录之二

这篇主要记录录屏和SFTP的实现。 录屏及视频播放 对于录屏及录屏的播放,因为我们的项目中需要把guacd和java后端分开两台服务器部署,而guacamole的录屏是通过guacd程序录制的。我的要求是在Java后端直接把录好的视频文件通过http前端播放,因…

数据结构(王卓版)——线性表

数据的存储结构之线性表 1、线性表的定义和特点

Python 图书管理系统 GUI界面 (源码在最后)

部分效果图: 部分源码: def creatPage(self):self.addPage AddFrame(self.root)#录入界面self.deletePage DeleteFrame(self.root) #删除界面self.countPage CountFrame(self.root) #统计界面self.register_admirPage Register_admirFrame(self.root…

内卷浪潮中的必考证书——CISP,抓住机会迅速上岸

近年来,随着网络空间安全日趋复杂,网络攻击、病毒入侵、信息失窃、信息泄密事件日益严重,信息安全保障工作被迅速提到了战略高度,能够构建全面的安全体系从而保障组织信息资产安全的专业人才非常紧缺,注册专业资质证书…

【运维知识进阶篇】Zabbix5.0稳定版详解10(Zabbix自动注册+Ansible自动部署,实现一条命令监控任意主机)

当我们的Zabbix自动注册Ansible自动部署在一起时,会碰出什么样的火花,答案就是可以实现执行ansible的一条命令,监控任意一台或多台主机。 目录 一、配置好自动注册规则 二、编写Ansible playbook 三、运行Ansible,查看监控效果…

【 Python 全栈开发 - 人工智能篇 - 41 】线性回归算法

文章目录 一、简介1.1 什么是线性回归?1.2 线性回归在人工智能中的应用预测分析特征工程异常检测 1.3 Python 在人工智能中的角色数据处理和分析机器学习和深度学习自然语言处理 二、理解线性回归2.1 线性回归的基本原理2.2 线性回归模型的假设2.3 线性回归的评估指…

Codeforces Round 875 (Div. 1) A. Copil Copac Draws Trees

题意 Copil Copac 给定了一个由 n−1 条边组成的列表,该列表描述了一棵由 n 个顶点组成的树。他决定用下面的算法来绘制它: 步骤 0:绘制第一个顶点(顶点1)。转到步骤1。 步骤 1:对于输入中的每一条边&#…

字符串模式匹配算法(暴力破解、KMP、BM、Sunday)

目录 暴力破解 KMP 算法 构造 next 数组 KMP代码 BM 算法 Sunday 算法 参考资料 又通过leetcode复习了之前的知识:找出字符串中第一个匹配项的下标 暴力破解 你的面前有两段序列 S 和 T,你需要判断 T 是否可以匹配成为 S 的子串。 你可能会凭肉眼立即得出结…

【亲测】python 安装 pillow报错 如何处理

今天在新系统上安装pillow库,提示错误: WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by SSLError(SSLEOFError(8, EOF occurred in violation of protocol (_ssl.c:997))): /simple/…