IOS 详解socket编程[oc]粘包、半包处理

发布时间 - 2026-01-10 22:59:31    点击率:

IOS 详解socket编程[oc]粘包、半包处理

在做socket编程时,如果是做tcp连接,那就不可避免的会遇到粘包与半包的问题,粘包就是多组数据被一并接收了,粘在了一起,无法做划分;半包就是有数据接收不完整,无法处理。要解决粘包、半包的问题,一般在设计数据(消息)格式时会约定好一个字段专门用于描述数据包的长度,这样就使数据有了边界,依靠这个边界,就能把每组数据划分出来,数据不完整时也能获知数据的缺失。

(当然也可以把数据设计成定长数据,但这样不够灵活;或者用\n,\r这类字符作为数据划分依据,但不直观、不明确,同时也不灵活)

举个栗子:

消息=消息头+消息体。消息头用于描述消息本身的基本信息,消息体则为消息的具体内容


如上图所示,假如我们的一个消息是这么定义的

消息头 = msgId(4B)+version(2B)+len(4B),共占用10字节

消息体 =  len中描述的16字节长

所以这条消息的长度就是 26字节

可以看到,要想知道一条完整数据的边界,关键就是消息头中的len字段

假如我们现在接收到的数据是这样的:


这个情况下即包含了粘包,也出现了半包的情况,三个数据包粘在了一起,最后一个数据包没有接收完全,出现了半包的情况,看看代码如何处理

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 
{ 
  while (_readBuf.length >= 10)//因为头部固定10个字节,数据长度至少要大于10个字节,我们才能得到完整的消息描述信息 
  { 
    NSData *head = [_readBuf subdataWithRange:NSMakeRange(0, 10)];//取得头部数据 
    NSData *lengthData = [head subdataWithRange:NSMakeRange(6, 4)];//取得长度数据 
    NSInteger length = [[[NSString alloc] initWithData:lengthData encoding:NSUTF8StringEncoding] integerValue];//得出内容长度 
    NSInteger complateDataLength = length + 10;//算出一个包完整的长度(内容长度+头长度) 
    if (_readBuf.length >= complateDataLength)//如果缓存中数据够一个整包的长度 
    { 
      NSData *data = [_readBuf subdataWithRange:NSMakeRange(0, complateDataLength)];//截取一个包的长度(处理粘包) 
      [self handleTcpResponseData:data];//处理包数据 
      //从缓存中截掉处理完的数据,继续循环 
      _readBuf = [NSMutableData dataWithData:[_readBuf subdataWithRange:NSMakeRange(complateDataLength, _readBuf.length - complateDataLength)]]; 
    } 
    else//如果缓存中的数据长度不够一个包的长度,则包不完整(处理半包,继续读取) 
    { 
      [_socket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据 
      return; 
    } 
  } 
  //缓存中数据都处理完了,继续读取新数据 
  [_socket readDataWithTimeout:-1 buffer:_readBuf bufferOffset:_readBuf.length tag:0];//继续读取数据 
}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# IOS  # 详解socket编程[oc]粘包、半包处理  # socket  # socket编程  # iOS开发项目- 基于WebSocket的聊天通讯(2)  # iOS开发项目- 基于WebSocket的聊天通讯(1)  # IOS开发网络篇—Socket编程详解  # iOS App通信之local socket示例  # iOS App之间的通信 local socket  # iOS应用中使用AsyncSocket库处理Socket通信的用法讲解  # IOS中使用 CocoaAsyncSocket​  # iOS 使用 socket 实现即时通信示例(非第三方库)  # 数据包  # 不完整  # 出现了  # 定长  # 也不  # 那就  # 就能  # 是这样  # 也能  # 这条  # 这类  # 希望能  # 要想  # 可以看到  # 我们现在  # 不可避免  # 所示  # 谢谢大家  # 但不  # 则为 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Firefox Developer Edition开发者版本入口  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  Laravel如何使用withoutEvents方法临时禁用模型事件  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  如何在宝塔面板中创建新站点?  Laravel如何为API生成Swagger或OpenAPI文档  *服务器网站为何频现安全漏洞?  Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】  如何在阿里云虚拟主机上快速搭建个人网站?  网站制作软件有哪些,制图软件有哪些?  微信推文制作网站有哪些,怎么做微信推文,急?  浅谈javascript alert和confirm的美化  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  JavaScript实现Fly Bird小游戏  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  深圳网站制作平台,深圳市做网站好的公司有哪些?  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践  如何用IIS7快速搭建并优化网站站点?  如何在 Telegram Web View(iOS)中防止键盘遮挡底部输入框  在Oracle关闭情况下如何修改spfile的参数  青岛网站建设如何选择本地服务器?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  微信小程序 require机制详解及实例代码  如何在阿里云购买域名并搭建网站?  如何快速生成专业多端适配建站电话?  Laravel怎么在Controller之外的地方验证数据  Laravel如何使用Blade组件和插槽?(Component代码示例)  Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?  Laravel如何使用Gate和Policy进行授权?(权限控制)  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  b2c电商网站制作流程,b2c水平综合的电商平台?  如何基于云服务器快速搭建网站及云盘系统?  如何快速搭建FTP站点实现文件共享?  Laravel模型关联查询教程_Laravel Eloquent一对多关联写法  详解jQuery中基本的动画方法  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  香港服务器租用每月最低只需15元?  Laravel定时任务怎么设置_Laravel Crontab调度器配置  HTML5段落标签p和br怎么选_文本排版常用标签对比【解答】  桂林网站制作公司有哪些,桂林马拉松怎么报名?  高性能网站服务器部署指南:稳定运行与安全配置优化方案  微信小程序 wx.uploadFile无法上传解决办法  Python并发异常传播_错误处理解析【教程】