实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncSocket来进行长连接连接和传输数据,该第三方地址:https://github.com/robbiehanson/CocoaAsyncSocket,读者可以自行google或者baidu搜索这个库的用法,网上有很多资料,而且用法不难。
在一些对Socket通信使用需求不是很高的应用中,比如需要多个iOS设备之间进行聊天即时通讯,这时候只要用这个CocoaAsyncSocket就基本能满足这个需求,但是在本人从事的直播项目中对Socket通信协议的需求就比较高,这个需求模式和游戏开发模式类似,因为游戏应用上就有很多数据变化是需要实时更新数据的,比如游戏的玩家生命值,如果在多人联网游戏平台上,你的设备上需要实时更新其他玩家的生命值数据,而其他玩家设备上也会实时更新你的生命值数据,这个需求通过http主动请求是不能满足需求,所以游戏开发一般都会有Socket通信。而在本人从事的直播项目后台所用的语言是erlang语言,后台对这Socket协议传输的数据有一个自定义的协议规则,例如下图:
图1-1
这协议就是一段可以在Socket传输的二进制流,后面第三部分协议数据流就是具体要传输的数据字段,
而这个协议数据流内容就是如下通过erlang的一个协议文档的示例:
// ========== 切换到新场景 ==========
message Cs_20001{
uint32 SceneId = 1; // 进入场景ID
uint32 Line = 2; // 分线,公共场景发0,多人副本后端会指定
}
message Sc_20001{
uint8 Res = 1; // 1成功 0异常 2不能进入该关卡 3已经处于关卡当是 4没这个地图或关卡 5今日进入BOSS关或普通关次数上限 6体力不足 7进入条件不足 8地图类型不存在 10 没参加BOSS活动,无法进入 11 BOSS战房间状态已经结束 12 次数不足 13 冷却时间不足 14无权进入这个BOSS房间 15进BOSS房间条件不足
uint32 SceneId = 2; // 现在所在的场景
uint8 Pos = 3; // 坐标点
uint8 Status = 4; // 人物状态 0 正常 10队长状态
uint8 Type = 5; // 前端标识
uint32 DefaultCombat = 6; // 推荐战斗力
}
先解释一下这个协议的一些定义:
Cs就是Client --> Server(客户端向服务器发送的数据协议),而Sc就是Server-->Client(服务器向客户端返回的数据协议)
本篇主要讲解请求模块,所以就讲这个Cs_20001请求协议封装数据包,这个20001就是这个协议的号,也叫协议ID(后面在代码中会用到)。
在Cs_20001中,有两个需要Socket发送给服务器的字段,都是uint32格式的,也是C语言的基本数据类型,但是在Socket传输中传输的是二进制流,也就是说,我们需要将这两个uint32格式的数据字段转为二进制数据,然后拼接成一条数据流,然后让这个数据流在Socket中传递到服务器,说到流如果学过Java的同学会对流的概念比较容易理解,如果没接触过流也没关系,就好比是一截水流从客户端流向服务器。其实这个数据流从客户端传递到服务器,这个过程也不是想象的那么简单,涉及到很多底层的Socket传输逻辑逻辑,但是CocoaAsyncSocket已经做好了这部分的封装,而且是OC面向对象的封装,我们只需要将需要传递的数据转为NSData通过CocoaAsyncSocket的代理方法传递过去就好了。
对于简单的需求,比如我仅仅只需要两台iPhone设备传递NSString字符串,只要将NSString转为NSData传递就好,但是对于我上面说的erlang服务器需要自定义的协议,就需要客户端更多的封包解包的逻辑了,这个封包,比如拿上面字段协议为例子,就是将Cs_20001的数据包按照图1-1中自定义的格式进行拼接数据,那么这时候在图1-1中的需要两个字节的协议号就是20001了,也就是说需要将20001用两个字节的存储空间存储,然后在图1-1中,协议数据流的内容就是uint32 SceneId和uint32 Line这两个字段拼接成的数据,而且协议规定了顺序拼接就是怎么样的顺序,这里uint32 SceneId当然是在前而uint32 Line在后,拼接好后,可以计算得出,这个协议数据流的字节数?bytes,然后+2(协议号的字节长度),再+4(消息总长度需要的四个字节),就得到整个协议流的长度,然后把这个总长度存储在四个字节的消息总长度中,当然整个协议流的拼接顺序还是如图1-1中所示,然后通过CocoaAsyncSocket传递给服务器就好。
下面就通过代码来讲解这个业务逻辑:
一、首先对后台提供的协议进行模型对象化,但凡有MVC基础就应该秒懂,其实就是MVC中的Model。