粘包的处理

TCP长连接会有粘包的问题存在。为什么?问度娘。

处理粘包的唯一方法就是制定应用层的数据通讯协议,通过协议来规范现有接收的数据是否满足消息数据的需要。在应用中处理粘包的基础方法主要有两种分别是以4节字描述消息大小或以结束符。

在此略过N多代码。

转载于:https://www.cnblogs.com/hnxxcxg/p/4574567.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.TCP是流传输,所以本质上不该称之为粘包,发送者和接收者都是自顾自的,要一段一段发得选UDP 现象是,你发出3个2048字节的包,发送时会被优化成4096/2048,或者跟之前的包合并,但是取出时却很随意,除了空载时的首个包,其他有可能拆成1-4096大小若干个包 2.“粘包”和“分包”很头疼,但是只要抓住第一个包,问题就解决了一大半 幸运的是,TCP发出的包不是乱序的,这有点像你按顺序写出字节集一样,只要你抓住头部的定义,就能轻而易举解构数据 为此,发送时,首个包要跟前一段数据流有时间间隔,好让之前的Recv操作完成(当然,条件允许可以Recv完成后反馈,发送端收到反馈消息再继续下一波) 3.定义协议结构,各有各的办法,以下代码仅作参考 .版本 2     pocket = 取空白字节集 (#pk_size)     DataAddr = 取变量指针 (pocket) + 8     pk_sign = 取字节集数据 (到字节集 (“P_KT”), #整数型, )     写数值ptr (DataAddr, #pk_sign, pk_sign)     写数值ptr (DataAddr, #pk_crch, CRC32all)     写数值ptr (DataAddr, #pk_crc32, CRC32all)     写数值ptr (DataAddr, #pk_SN, 集_SN)     写数值ptr (DataAddr, #pk_remain, size)     CRC32pk = CRC32_PTR (DataAddr, #pk_size)     写数值ptr (DataAddr, #pk_crch, CRC32pk) 4.使用哈希表存储分包数据 我认为哈希表存储的方式是线程安全的,客户句柄是唯一的,一个客户甚至分不到一条线程,该句柄对应的数据地址是唯一的,所以不会出现两条线程同时操作一个内存地址的情形 当然,出现碰撞时,插入链表这个操作不是线程安全的,这个以后优化 5.星光极速模块我只稍微改了一下,把原先字节集操作改成指针操作 6.没有选择HP-socket的原因是太庞大了,用来做服务端可以,但是如果作为客户端即使是静态库,编译之后也很大 7.目前涉分包组包的代码不多,其他的运用过程中不断改进 关于哈希表的部分,我专门开了个帖子 https://bbs.125.la/forum.php?mod=viewthreadtid=14659403
.版本 2 .支持库 spec .支持库 sock .程序集 窗口程序集_启动窗口 .子程序 _按钮2_被单击 客户1.发送数据 (取重复字节集 (10000, 到字节集 (“1”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (20000, 到字节集 (“2”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (30000, 到字节集 (“3”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (40000, 到字节集 (“4”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (50000, 到字节集 (“5”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (60000, 到字节集 (“6”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (70000, 到字节集 (“7”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (80000, 到字节集 (“8”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (90000, 到字节集 (“9”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (100000, 到字节集 (“0”)) + 到字节集 (“结尾符”)) .子程序 _服务器1_数据到达 .局部变量 取回数据, 字节集 .局部变量 数据数组, 文本型, , "0" .局部变量 次数, 整数型 .局部变量 临时数据, 字节集, 静态 .局部变量 得到的封包, 文本型 取回数据 = 服务器1.取回数据 () .判断开始 (取字节集右边 (取回数据, 6) ≠ 到字节集 (“结尾符”))  ' 6为结尾符的长度;这里检测封包是否全部发送完毕,如果没有发送完毕就会把发送来的封包数据进行累加     临时数据 = 临时数据 + 取回数据 .默认     临时数据 = 临时数据 + 取回数据  ' 检测到结尾符出现,说明数据已经发送完毕,这里把最后发送来的带有结尾符的数据加上就OK了。     临时数据 = 子字节集替换 (临时数据, 到字节集 (“结尾符”), , 取字节集长度 (临时数据) - 6, 6)  ' 6为结尾符的长度;这里把结尾符替换尾空,剩余数据尾完整的纯净数据。     数据数组 = 分割文本 (到文本 (临时数据), “分隔符”, )  ' 这里把收到的数据进行分割处理,无论服务器发送了多少次,都统一按分隔符分割     调试输出 (“封包数量:” + 到文本 (取数组成员数 (数据数组)))     .计次循环首 (取数组成员数 (数据数组), 次数)         得到的封包 = 数据数组 [次数]  ' 这里得到分割后的封包文本。         调试输出 (“第” + 到文本 (次数) + “个封包的大小:” + 到文本 (取文本长度 (得到的封包)))  ' 这里的大小和上面发送封包的大小相同,可以看到封包的分割次数。     .计次循环尾 ()     临时数据 = {  } .判断结束 .子程序 __启动窗口_创建完毕 客户1.连接 (取本机名 (), 8888)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值