关于TCP的粘包问题

简单的说就是通过TCP协议发送了多条独立的数据,但接收的时候,有些数据不幸的合并成了一个。比如客户端向服务器发送两个命令:”Start””Parameter[x.x.x]”,第一个命令的含义是开始,第二个命令的含义是启动参数。但是服务器接收的时候,很可能不是分两次接收,而是一次接收到”StartParameter[x.x.x]”,这下全乱了。
UDP丢包是因为数据包在传送过程中丢失了 而TCP是基于流式的发送 并且存在丢包重发机制 TCP是可靠连接而UDP是不可靠的这个我就不多说了

关于TCP的粘包 正是由于TCP是流式传送的 也就是连接建立后可以一直不停的发送 并没有明确的边界定义 而你用UDP发送的时候 是可以按照一个一个数据包去发送的 一个数据包就是一个明确的边界

而TCP并没有数据包的概念 是完全流式的 他会开辟一个缓冲区 发送端往其中写入数据 每过一段时间就发送出去 然后接收端接收到这些数据 但是并不是说我发送了一次数据就肯定发送出去了 数据会在缓冲区中 有可能后续发送的数据和之前发送的数据同时存在缓冲区中随后一起发送 这就是粘包的一种形式 接收端也有产生粘包的情况 如果应用程序没有及时处理缓冲区中的数据 那么后续到达的数据会继续存放到缓冲区中 也就是2次接收的数据同时存在缓冲区中 下次取缓冲区的时候就会取出2次粘包后的数据 这是粘包的另外一种形式 还有其他许多形式 比如填充缓冲区到一半缓冲区满了直接发送了 但是其实那个包还没填充完全 这个就是不完整的粘包了 剩余数据会在下次发送的时候补上关于解决方法 如果你是连续的整个数据流 比如发送文件 那么完全不考虑粘包也无所谓 因为可以建立连接后发送 发送完毕后断开连接 整个数据流就是整个一个文件 无论数据从那里切开都无所谓 整个拼接后依旧是整个一个文件的数据
如果你发送的数据是多次通信 比如把一个目录下所有的文件名都发送过去 那么就不能当作一个整体发送了 必须对他们划分边界 有一个很简单的处理方法 就是采用"数据长度+实际数据"的格式来发送数据 这个"数据长度"的格式是固定宽度的 比如4字节 可以表示0~4GB的宽度了 足够用了 这个宽度说明了后续实际数据的宽度 这样你就可以把粘包后的数据按照正确的宽度取出来了

每次都是取出4字节 随后按照正确的宽度取出后续部分的就OK了
如果你的所有数据都是固定宽度的 比如不停的发送温度数据 每个都是1字节 那么宽度已知了 每次你都取出一个1字节就OK了 所以就不用发送宽度数据了

当然你也可以按照建立连接断开连接来划分边界 每次发送数据都打开关闭一次连接 不过对于频繁的小数据量是不可取的做法 因为开销太大 建立连接和关闭连接也是需要耗费网络流量的
总而言之 粘包的情况是无法绝对避免的 因为网络环境是很复杂的 依赖发送和接收缓冲区的控制是不能保证100%的 只要在发送的数据中说明数据的宽度随后在接收部分按照这个宽度拆开就OK了 宽度全都是统一的已知宽度的情况下拆开更加容易 连在发送端填入宽度数据都可以省去了

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

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

相关文章

运行第一个node.js文件

安装node.js 链接:https://nodejs.org/en/ 选择downloads 再选择对应的版本,Windows Installer (.msi):表示需要安装后才能运行node.js文件,安装完后在(cmd)控制台输入node -v查看版本,不用配置环境安装完成后自动配置。Windows Binary (.zip…

spark异常 - Null value appeared in non-nullable field

主要代码如下 val rddsc.newAPIHadoopRDD(hBaseConf, classOf[TableInputFormat], classOf[ImmutableBytesWritable],classOf[Result])import spark.implicits._val value :RDD[UserSchemaClass] rdd.map(convertHive)val tempDS value .toDF()tempDS.createTempView("te…

关于回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件…

Java 汉字转拼音 Scala 汉字转拼音

汉字转拼音 Maven引用 <dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version></dependency> Scala Demo: import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFor…

中科慧眼双目安装pcl

1 step 安装依赖 sudo apt-get update //更新ubuntu的软件源 //安装依赖 sudo apt-get install git build-essential linux-libc-dev sudo apt-get install cmake cmake-gui sudo apt-get install libusb-1.0-0-dev libusb-dev libudev-dev …

链式调用-普通调用

var http require(http);/*创建一个web服务器-链式调用*/ http.createServer(function (req, res) {/*给服务器传入一个匿名的回调函数&#xff0c;req获取请求相关的信息&#xff0c;例如&#xff1a;请求的类型是get还是post&#xff0c;res告诉服务器给请求响应内容*/res.w…

Spark 调用 hive使用动态分区插入数据

spark 调用sql插入hive 失败 &#xff0c;执行语句如下 spark.sql("INSERT INTO default.test_table_partition partition(province,city) SELECT xxx,xxx md5(province),md5(city) FROM test_table") 报错如下&#xff0c;需动态插入分区 Exception in thread &q…

cmakelists 指定opencv版本

利用以下命令查看版本&#xff1a; locate OpenCVConfig.cmake 打印&#xff1a; /opt/ros/kinetic/share/OpenCV-3.3.1-dev/OpenCVConfig.cmake /usr/local/lib/cmake/opencv4/OpenCVConfig.cmake 指定版本&#xff1a; set(OpenCV_DIR "/usr/local/lib/cmake/openc…

nodejs异步读取文件与同步读取文件的区别

var fsrequire(fs);//引入他的模块之后调用读取文件的方法 fs.readFile(file.txt,utf-8,function(err,data){//回调函数有两个参数&#xff0c;一个是err表示错误信息&#xff0c;一个是读取文件的内容if(err){console.log(err);}else{console.log(data);} }); console.log(&qu…

phoenix-sqlline 连接失败

报错如下 [rootxxx bin]# phoenix-sqlline.py xxx.xxx.xxx:2181:/hbase Traceback (most recent call last):File "/opt/cloudera/parcels/APACHE_PHOENIX-4.14.0-cdh5.13.2.p0.3/bin/../lib/phoenix/bin/sqlline.py", line 25, in <module>import phoenix_ut…

TCP解决connect函数的超时问题

在一个TCP套接口被设置为非阻塞之后调用connect,connect会立即返回EINPROGRESS错误,表示连接操作正在进行中,但是仍未完成;同时TCP的三路握手操作继续进行;在这之后,我们可以调用select来检查这个链接是否建立成功;非阻塞connect有三种用途:1.我们可以在三路握手的同时做一些其…

node.js异步式IO与事件式编程

Node.js最大的特性就是异步式I/O与事件紧密结合的编程模式。这种模式与传统的同步式IO线性的编程思路有很大的不同&#xff0c;因为控制流很大程度上要靠事件和回调函数来组织&#xff0c;一个逻辑要拆分为若干个单元格。内容&#xff1a;阻塞和线程1.同步式I/O或阻塞式I/O线程…

几个重要库函数的实现

面试官很喜欢让求职者写一些常用库函数的实现&#xff0c;有很多是和字符串相关的&#xff0c;有一些是关于内存拷贝的。一般&#xff0c;常会让写的函数有以下几个&#xff1a; strcpy &#xff0c; strncpy&#xff0c; memcpy。 memset一般不会让去写&#xff0c;但这个函数…

CDH 5.13.0 集成 Phoenix

1.下载Phoenix http://phoenix.apache.org/download.html 找到对应版本 点击parcels (cdh可安装版本) http://www.apache.org/dist/phoenix/apache-phoenix-4.14.0-cdh5.13.2/parcels/ 下载好这三个文件 -rw-r--r-- 1 root root 364830720 7月 26 16:15 APACHE_PHOENIX-…

四元数,欧拉角,旋转矩阵相互转换

#include <TransForms3d/TransForms.h>/*---------------------------------------角度弧度转换----------------------------------------*/ /*** description: 角度转为弧度* param {double} angle 角度值* return 返回对应弧度值,一般在-3.14~3.14之间*/ double Trans…

node.js事件

// 1.普通事件的使用var EventEmitterrequire(events).EventEmitter;//声明事件对象 var eventnew EventEmitter();//实例化对象 event.on(some_event,function(){//注册事件并给事件取个别名some_eventconsole.log(这是一个自定义的事件); }); setTimeout(function(){//触发事…

Phoenix 关联hbase表历史数据

Phoenix 基本使用 进入Phoenix phoenix-sqlline.py 10.248.161.18:2181:/hbase 或者进入目录下执行 cd /opt/cloudera/parcels/APACHE_PHOENIX/bin 关联Hbase原有表 创建Hbase表&#xff0c;列簇为 cf1 , cf2 create phoenix_hbase_test,cf1,cf2 插入测试数据 put phoenix…

C++面试(二)

笔试题&#xff1a; Char * const p,char const *p,const char *p分别表示什么意思? 面向对象的三个特性是什么&#xff0c;有什么意义&#xff1f; 编程实现字符串连接函数 char * strcat(char *strDest,const char *strsrc);不用C/C字符串处理库函数。 ISO七层参考模型是什…

C++面试(三)

笔试题&#xff1a; 1 写出按一个字节的位对其方式的命令 #pragma pack(n) 2 写出UpdateData(BOOL values)函数的作用 3 写字符串拷贝函数&#xff0c;不能用系统的strcpy; Char *Strcpy(char *str, const char *Srcstr); 4 对两个有序的链表head1,head2&#xff0c;把他们合并…

Phoenix 关联映射 Hbase表 获取不到数据,upsert hbase 列名为16进制字符

创建Hbase表 create phoenix_hbase_test,cf1,cf2 put phoenix_hbase_test, key1,cf1:name,zhangsan put phoenix_hbase_test, key1,cf2:age,18 put phoenix_hbase_test, key2,cf1:name,lisi put phoenix_hbase_test, key2,cf2:age,26 put phoenix_hbase_test, key3,cf1:name,c…