相关文章推荐
酷酷的烈马  ·  java 调用 ...·  2 周前    · 
捣蛋的长颈鹿  ·  php ...·  5 月前    · 
近视的沙发  ·  selenium中接受alert_lion_ ...·  1 年前    · 

【仅用于技术交流,未经允许禁止转载】
通常APP-Server使用http协议,告诉APP需要的展示内容图片,文字。这是一种最为常见的协议了。另外一种客户端内协议,比如新闻APP,点击一个焦点新闻,APP跳到相应的频道或专题。不难发现:前者是Server->APP通信,主要是内容类型的,后者是APP<—>APP内通信,主要是命令、动作类型的。
如何更好的处理APP内通信,这里有必要先介绍一下iOS平台进程间通信。

进程间通信

以iOS平台为例,进程间通信IPC,可以通过自定义URL Schema,然后APP实现-(BOOL) application:(UIApplication *) openURL:(NSURL *) sourceApplication:(NSString *) annotation:(id) 方法,可以处理一些命令和参数。其中sourceApplication即调用者的bundleIdentifier。比如下面这条URL,会调起twitter客户端,并拉起发送推文的界面。


URL Scheme完美解决了同一个操作系统中,调用APP和传输消息和命令的问题。URL Schema机制,给开发者提供了很好的思路,可以解决APP内通信问题。CPMessage应运而生。

什么是CPMessage

CPMessage(Cross Platform Message跨平台消息)可以当做服务器/客户端(让客户端处理一些命令),或者客户端内部通信的桥梁。通信的发起者可能是服务器、Push、用户操作、HTML5或者是别的APP。客户端根据具体命令和相应参数,执行相应动作。总之,CPMessage思路源于iOS平台的URL Schema机制。

CPMessage的机制

为了确保多平台的一致性,使用协议名称CPM作为开头,只是传递协议的方式不同。在iOS上,向客户端通信的方式是scheme+protocol,例如:
cpm://message.cmd?messageID=MsgID&urls=EncodedURLStrings&uid=uid&ex1=ex1&ex2=ex2&ex3=ex3
下面将各部分标注一下:

一般来说:命令名称都是message.cmd,经常改变的是messageID(下面详细介绍)。参数列表中,messageID表明是那种动作,比如,打开一个webview、打开新的页面、还是调起登录框等。参数列表后面是一些辅助参数。下面的表格给出了一些示例。

参数 用途 格式 示例
MessageID 用来指定客户端做出的响应 string 1.1
url 需跳转的网址 string www.baidu.com
ex1 额外参数 string “03”

另外,如果ex1、ex2和ex3不够用。还可以使用more参数。比如:more = {"title":"helloworld","name":"jack"};more参数格式为json格式。方便客户端解析字段。

MessageID

MessageID根据可分为mainID和subID,比如MessageID=2.1。那么mainID是2,subID是1。一般来说mainID是操作类型的区分,比如:
mainID=1表示打开页面。
mainID=2是传递数据。
mainID=3 是打开其他sdk等等。
subID则是一些操作的细分类型,比如:打开那个页面等等。
APP都是跨平台的,至少有iPhone,Android客户端,那么URL Schema头部将是不同的。举例:Server给的H页面中,某个链接是个CPM消息,URL Scheme配合CPM的使用,如下格式:

myapp://cpm://xxxxxx。操作系统级别会读取到“myapp://”从而拉起客户端,客户端内部读取到“cpm://”

CPMessage的使用

开发者如何应用CPMessage到自己的APP中呢?你需要做三件事:
第一 ,提前注册一些UIViewController和方法,封装成一个个CPMessageItem。
第二 ,当CPMessage过来的时候,将其解析成CPMessageCommand,其中CPMessageCommand包含了参数。
第三 ,使用一个CPMManager类,将command 和 item对应到某一个UIViewController,并使用NSInvocation,调用之前注册好的方法。
那么,回到刚才一开始的问题 ,我们假设MessageID = 1.1 即跳转频道,ex1即频道的index。那么,Server将下面的URL消息,封装到焦点新闻里
cpm://message.cmd?messageID=1.1&ex1=03
客户端TabViewController注册一个调转频道的method -(void) switchToChannel:(int)index,执行CPMManager,TabViewController 执行switchToChannel方法。可以很优雅的解决新闻APP,调转到任意频道的问题。

CPMManager的UML图+流程图


CPMManger 的几个关键函数
prepareProcessor 事先注册好一些类和类方法
handleUrl: 接收url,带有cpm schema的url
onCPMIsComing :参数是CPMCommand
handleCPM :参数CPMCommand。最终通过[NSInvocation invoke]实现回调。

CPMManger的实现

这里只列出部分代码,即CPMManger的关键代码:

//向CPMParse注册的回调函数。
- (void)onCPMIsComing:(NSNotification *)noti
    NSDictionary *userInfo = noti.userInfo;
    if ([userInfo isKindOfClass:[NSDictionary class]]) {
        CPMCommand *command = [userInfo objectForKey:kCPMessageParserNotificaitonCommandKey];//
        if ([command isKindOfClass:[CPMCommand class]]) {
            [self handleCPM:command];
//真正处理CPMessage的地方。通过NSInvocation将message命令和UIViewController关联起来
- (void)handleCPM:(CPMCommand *)message
    [self prepareProcessors];
    CPMItem *item = (CPMItem *)[self.processors objectForKey:NSStringFromCPMessageCommand(message)];
    if (nil == item) {
        return;
    [item getInfoFromCPMessageCommand:message];
    UIViewController *visibleCtrl = [self.assit topViewController];
    Class receiverClass = NSClassFromString(item.className);
    if (item.classMethod != nil) {
        [self performClassSelector:item.classMethod onTarget:receiverClass withArgs:item.classArgs];
        [item clearInfoFromCPMessageCommand];
    } else if (!item.isOpenAsNew && [visibleCtrl isMemberOfClass:receiverClass]) { // if target viewcontroller is top viewcontroller
        if (item.reloadMethod != nil) {
            [self performSelector:item.reloadMethod onTarget:visibleCtrl withArgs:item.initialArgs];
        } else if (item.optMethod != nil) {
            [self performSelector:item.optMethod onTarget:visibleCtrl withArgs:item.optArgs];
        } else {
            // no reloadSEL and no optSEL then do nothing
        [item clearInfoFromCPMessageCommand];
    } else {
        UIViewController *baseCtl = [item.processor perpareOpeningWithHelpFrom:self.assit];
        //必须要dispatch_async,否则不会回调viewWillDisappear和viewDidDisappear
        dispatch_async(dispatch_get_main_queue(), ^{
            // if target viewcontroller is top viewcontroller
            if (!item.isOpenAsNew && [baseCtl isMemberOfClass:receiverClass]) {
                if (item.reloadMethod != nil) {
                    [self performSelector:item.reloadMethod onTarget:baseCtl withArgs:item.initialArgs];
                } else if (item.optMethod != nil) {
                    [self performSelector:item.optMethod onTarget:baseCtl withArgs:item.optArgs];
                } else {
                    // no reloadSEL and no optSEL then do nothing
            } else {
                id receiverSuper = [receiverClass alloc];
                id receiver = [self performSelector:item.initialMethod onTarget:receiverSuper withArgs:item.initialArgs];
                if (nil == receiver || ![receiver isKindOfClass:[UIViewController class]]) {
                    [receiverSuper release];
                } else {
                    [item.processor doOpen:receiver on:baseCtl];
                    [receiver release];
            [item clearInfoFromCPMessageCommand];
  NSInvocation 施展才华的地方,selector和args 调用方法。
- (id)performSelector:(SEL)aSelector onTarget:(id)target withArgs:(NSArray *)args
    id ret = nil;
    if (aSelector == nil || target == nil || ![target respondsToSelector:aSelector]) {
        return ret;
    NSMethodSignature *signature = [target methodSignatureForSelector:aSelector];
    if (args.count + 2 != signature.numberOfArguments) {
        return ret;
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:aSelector];
    [invocation setTarget:target];
    for (int i = 2, j = 0; j < args.count; i++, j++) {
        id arg = [args objectAtIndex:j];
        [invocation setArgument:&arg atIndex:i];
    [invocation invoke];
    NSUInteger length = [[invocation methodSignature] methodReturnLength];
    //    void *buffer = (void *)malloc(length);
    if (length > 0) {
        [invocation getReturnValue:&ret];
    return ret;
- (id)performClassSelector:(SEL)aSelector onTarget:(Class)target withArgs:(NSArray *)args
    id ret = nil;
    if (aSelector == nil || target == nil) {
        return ret;
    NSMutableString *argsInCTypes = [NSMutableString stringWithString:@"v"];
    for (int i = 0; i < args.count; ++i) {
        [argsInCTypes appendString:@"@:"];
    NSMethodSignature *signature = [target methodSignatureForSelector:aSelector]; // [NSMethodSignature signatureWithObjCTypes:argsInCTypes.UTF8String];
    if (signature == nil || args.count + 2 != signature.numberOfArguments) {
        return ret;
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:aSelector];
    [invocation setTarget:target];
    for (int i = 2, j = 0; j < args.count; i++, j++) {
        id arg = [args objectAtIndex:j];
        [invocation setArgument:&arg atIndex:i];
    [invocation invoke];
    NSUInteger length = [[invocation methodSignature] methodReturnLength];
    //    void *buffer = (void *)malloc(length);
    if (length > 0) {
        [invocation getReturnValue:&ret];
    return ret;
//将UIViewController 的类名、selector分离出来,存到processor中。
- (void)prepareProcessors
    NSMutableDictionary *processors = [NSMutableDictionary new];
    CPMType type = -1;
    CPMItem *item = nil;
    //////////////////////////////////////////////////////////////////////////
    type = CPMessageTypeSingleHTML5;
    item = [CPMItem CPMessageItemWithProcessor:[CPMessageProcessors CPMessageProcessorForMessage:type]
                                     className:@"WebViewController"
                                   classMethod:nil
                                    initMethod:@selector(initWithsURL:title:)
                                  reloadMethod:@selector(loadWithsURL:title:)
                                     optMethod:nil];
    if (IS_VALID_CPMessageTYPE(type) && (nil != item)) {
        [processors setObject:item forKey:CPMessageKeys[type]];
        item = nil;
//添加其他item
    self.processors = processors;
    [processors release];
				Android手机app与服务器端进行通信(一)正文当前手机app与服务器端通信,通常有两种方式,一种是长连接,利用Socket进行连接,另一种是短连接通过Http进行连接。相较而言,短连接不损耗系统...
											来自:	 qq_15764903的博客
				在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次...
											来自:	 程序员宜春的博客
				本文讲述了:    1、如何在Android上搭建Mina服务端(使用Mina 2.0.15、编程环境Eclipse);   2、如何在iOS上建立Socket客户端(使用CocoaAsyncSock...
											来自:	 沃克哈德の博客
				手机APP与服务器通讯协议选择开发手机APP相关项目,手机APP通常大量使用HTTP协议与服务器通信,这样手机可以主动从服务器获取所需要的数据,但是如果要让服务器主动与手机通信,让手机去做一件事情该怎...
											来自:	 软件架构农
				 通用的语言有很多种,例如英语和中文,在网络的通讯中,通用的协议有很多,其中http是被最广泛使用的。如果是私有的协议,那就只能自己设计了。  用http是最方便的,如果是私有协议,包含协议的封装和拆...
											来自:	 weixin_34313182的博客
				对于php开发环境套件Appsever的安装与配置第一步 :下载Appsever下载的链接:https://www.appserv.org/en/进去之后:下载完成后是这个样子的:第二步:双击下载好的...
											来自:	 qq_40862118的博客
				简单列一下不同协议,序列化方式等的考虑。http还是私有协议?http协议优/缺点:在服务器端只需要提供一份接口,浏览器和app共用。在app中嵌入web view也很容易。http协议的相关工具非常...
											来自:	 横云断岭的专栏
				分享一个百度智能手环开源项目的设计方案资料。项目简介百度云智能手环的开源方案是基于Apache2.0开源协议,开源内容包括硬件设计文档,原理图、ROM、通讯协议在内的全套方案,同时开放APP和云服务的...
											来自:	 cpongo1的测试
				一:https保证通道安全二:下发token保证无登录的用户不能随意调用服务三:token有过期时间,保证服务不被长期木马攻击四:对于支付等安全功能,需要另外增加支付密码校验和短信验证五:应用层内做自...
											来自:	 益思于笔滴,识广于累积
				App测试中ios和Android的区别:1、Android长按home键呼出应用列表和切换应用,然后右滑则终止应用;2、多分辨率测试,Android端20多种,ios较少;3、机操作系统,Andro...
											来自:	 May_zhang的博客
				1.TCP协议:TCP协议是自IP协议出来又一常用的信息传输协议。是一个基于链接的、安全的、双向的传输协议现在,TCP协议一般都喝IP协议共同使用,我们称之为TCP/IPTCP说白了就是在互联网扩张时...
											来自:	 Chaz.Zhao' s Blog
				一、协议1、TCP2、UDP3、TCP/IP4、HTTP5、HTTPS1、HTTP协议:基于TCP连接的,主要解决如何包装数据,对应于应用层; 2、TCP/UDP协议:主要解决数据如何在网络中传输,对...
											来自:	 Mazy's Blog
				一、HTTP协议简介    1、协议    指计算机网络中两个计算机之间进行通信所必须遵守的规定或规则。    2、HTTP协议    是一种超文本传输协议。它允许将超文本标记语言(HTML)文档从W...
											来自:	 你关注了我,是个概率极低的事件......
				文章目录一、APPPOST数据到服务器二、APP从服务器GET数据三、APP界面部分四、相关疑问五、学习方法一、APPPOST数据到服务器  首先post的数据应该包括识别这个花卉的信息和我们想要浇水...
											来自:	 Beyonderwei的博客
				前言:接着补充app后台(也叫服务端开发)的基础知识。基础要夯实,不然哪来的万张高楼?正文:问1:整个前台后台交互的流程是个什么样子?答:基于http协议的app前后台交互包含以下几个步骤:1.建立连...
											来自:	 简简简简abc
			这一篇跟大家分享 Web 客户端/网页与 Web 服务器的通信过程,并详细讲述通信协议:HTTP 协议和 TCP 协议。
无论你是前端开发者还是后端开发者,以及测试工程师,这篇文章的知识都是你需要弄懂的。
读完这一篇文章,将全面弄懂 HTTP 协议、TCP 协议,面试官再也难不倒你相关知识。
下面为文章目录:
- Web 客户端和服务端通信过程;
    - 会讲解 TCP/IP 协议族、数据处理流程、 URL 到服务器访问步骤、七层网络模型;
- HTTP 协议;
    - 将详细 HTTP 介绍、特点、工作流程和原理、长连接、短连接;
    - 详细介绍请求报文、响应报文、HTTP 状态码、首部(通用首部、请求首部、响应首部、实体首部);
    - 讲解 GET 和 POST 的区别;
    - 讲解 HTTP2 新特性: 单一长连接、多路复用、二进制分帧、服务器推送;
- TCP 协议;
    - 介绍 UDP、TCP 协议;
    - 讲解 TCP 相关机制: 三次握手、四次挥手、超时重发、应答机制、窗口控制。
*当前内容版权归码字科技所有并授权显示,盗版必究。[阅读原文](http://gitbook.cn/gitchat/activity/5ca1ee4e99783b2694026d8f)*
				 //联系人:石虎 QQ:1224614774 昵称:嗡嘛呢叭咪哄 /** 提交审核的时候提示要更新协议操作步骤:  */ 一、登录iTunes Connect 1.登录 iTunes Connect...
											来自:	 石虎
			各位同行们好,小弟想问一下,app这样与硬件进行数据交互,智能控制。走的是什么协议?是TCP/IP么?我想研究下,但还有点抓不到学习方向,有没有大神指点下,我该看哪方面的书,或者有没有文档链接之类的。
			我最近对这个比较感兴趣 希望着手尝试一下 就先从网上找了一个别人做的类似美团一样的购物app 整个代码包都有 我想自己试着研究一下 就在阿里云买了一个服务器 照着网上配置了windows server 2008的环境  但是现在就一筹莫展了 该怎么实现app与服务器的连接??现在在手机端只能停留在登录界面 响应连接超时  求大神指点
				转载 http://www.52im.net/thread-1536-1-1.html1、前言相信活跃在即时通讯网社区的开发者们都很清楚,即时通讯应用(包括IM聊天应用、实时消息推送应用等)的流量消耗...
											来自:	 周镇怀的博客
				Android网络编程分为两种:基于http协议的,和基于socket的。基于Http协议:HttpClient、HttpURLConnection、AsyncHttpClient框架等基于Socke...
											来自:	 warmor的专栏
			想做一个app,大体上类似于云笔记,但是不知道该做用户的注册,验证,登陆,注销, 鄙人对后台不太熟悉,请教后台该如何做用户的验证呢,android app又该如何与服务器通讯呢?
				学习webAPP视频,逐步实现阅读界面。内容总结:首先实现下边栏模块。先设置好dom模块的架构,在设置css样式。知识点1:设置背景色可以利用两层div,一层是背景色,一层是内容框,覆盖并存。&amp...
											来自:	 m0_37727198的博客
				转载请标明出处:一片枫叶的专栏上一篇文章中我们讲解了App的数据统计,其主要分为两种:使用第三方服务统计和自身实现数据统计。一般而言我们使用第三方统计服务已经可以很好的满足我们的也无需求了,只是部分数...
											来自:	 一片枫叶的专栏
			我最近想做一个东西,架个server和手机app搭配做些东西。 目前是纯学习预研... 想请各位比较熟悉的牛人推荐几款学习学习。 之前server只玩过asp,上学的时候做过网站,不过挺久远了,也忘得
				1、前言最近暴雨不断,只能宅在家里,闲来无事,写写文章2、整体分析通过抓包工具,简单看看登陆封包内容,如下: 其中密码为123456 登陆,封包如下: 居然是明文传输密码和账号,不止如此,传输居然采用...
											来自:	 csky的博客
				【一个完整直播app架构】【一个完整直播app技术点】直播音视频知识点概括1.采集视频、音频1.1 采集视频、音频编码框架 AVFoundation:AVFoundation是用来播放和创建实时的视听...
											来自:	 fanenqian的博客
				点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私......
											来自:	 爱开发