mac TeamTalk开发点点滴滴之一——DDLogic框架分解下

4 TCP/IP长连接

大部分客户端应用程序的网络I/O模型采用阻塞模式就够用了,如遇到UI和网络需要异步,很常用的一种实现方式是启用多线程将网络数据的收发放到工作者线程中去。但是对网于IM这种应用场景来说阻塞模式就不适用了,试想聊天过程中你和服务器之间的交互是多么的频繁,你可以同时和几十位用户一起聊天,为了不阻塞难道每次聊天收发信息都需要建立一个线程来实现吗?这当然是不现实的,所以我们需要选择非阻塞模式异步socket IO。下面分别讲讲mac pro 和 windows的网络异步I/O的实现。

mac TT

mac TT得益于oc提供的良好平台目前借助的是CFNetwork和NSStream类实现TCP/IP 异步I/O socket,利用CFNetwork创建socket通信通道,利用NSStream传递单向的数据流,具体实现如下: 
通过在NSStream中增加一个类方法扩展用于建立TCP/IP连接的一系列过程。

+ (void)getStreamsToHostNamed:(NSString *)hostName port:(NSInteger)port inputStream:(NSInputStream **)inputStream outputStream:(NSOutputStream **)outputStream
{
    CFHostRef           host;

    CFReadStreamRef     readStream;

    CFWriteStreamRef    writeStream;

    host = CFHostCreateWithName(NULL, (__bridge CFStringRef) hostName);

    CFStreamCreatePairWithSocketToCFHost(NULL, host, (SInt32)port, &readStream, &writeStream);

    CFRelease(host);

    ...
}

NSStream的两个派生类NSInputStream/NSOutputStream把整个socket通信抽象成了一个输入/输出流,通过oc平台的RunLoop将异步I/O事件通知到如下回调函数中:

-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
   switch(eventCode) {
      ...
   }
}

回调通知的事件有:

typedef NS_OPTIONS(NSUInteger, NSStreamEvent) {

    NSStreamEventNone = 0,

    NSStreamEventOpenCompleted = 1UL << 0, //输入or输出流打开成功即socket连接建立成

    NSStreamEventHasBytesAvailable = 1UL << 1, //可以接受数据通知即输入缓冲区有内容了

    NSStreamEventHasSpaceAvailable = 1UL << 2, //可以发送数据通知即输出缓冲区空了

    NSStreamEventErrorOccurred = 1UL << 3, //错误通知

    NSStreamEventEndEncountered = 1UL << 4

};
   以上具体代码可以参见mac tt代码NSStream+NStreamAddtion.m 以及 MGJMTalkClient.m

咋样整个过程看下来是不都看不到socket的影子?这样做有啥好处呢?我自己的理解最大的好处是足够简单,对于调用者来说socket的整个过程是透明的,调用者不需要去理解操作系统对异步socket的I/O模型的支持,不需要去理解socket建立的整个过程等。类似的还有java的NIO甚至netty库都把整个socket过程隐藏在了一个流的概念中。 
尽说好处了,差点忘记目前DDLogic的这种实现还有一个很大的问题(PS:是不是我们使用上有问题,同学们也可以帮忙看下),即connet TCP服务器的时候,回调事件里面肿么也收不到连接断失败的事件通知,导致整个TCP/IP流程不流畅,我们暂时采用了一个很龌龊的方式是:connet TCP服务器的时候设置个定时器,如果3秒钟没有收到连接建立成功的通知就认为连接失败了。这里的代码我担心也会为将来开发IOS TT埋下一个隐患,建议IOS开发同学去深入研究下或者寻找更好的技术选型。这里提供几个参考

  1. OC平台OS层的基于C的 BSD socket,这一层面提供的是socket原生态的方法,可以最大程度的控制网络编程,但是工作量也是最大的,和windows TT采用C/C++ 进行socket编程差不多。
  2. OC平台Core Foundation层提供的CFNetwork C ,对OS层的BSD socket做了一层简单的包装,并且和系统的run loop结合起来,使得异步socket I/O实现起来很方便。上面mac TT用的其实就是这一层,所以这里还是需要去深入研究上面的坑。
  3. OC平台最上层提供的Bonjour库,同学们可以自行去看下Networking and Bonjour on iPhone
  4. 另辟蹊径不走OC平台提供的库,用libevent来实现,不过对于客户端来说使用该库可能略重,但是它良好的封装使得使用起来非常简单而且本身也是轻量级高性能的网络库,客户端选择POSIX select或windows select模型足够用了。

windows TT 
windows TT是基于windows的WSAAsyncSelect模型建立的异步I/O,利用这个模型应用程序可在一个套接字上,接收以Windows消息为基础的网络事件通知,对于一个客户端程序已经足够用了。code projct有个对该模型很好的包装,同学们可以去看下(http://www.codeproject.com/Articles/3855/CAsyncSocketEx-Replacement-for-CAsyncSocket-with-p)。具体的实现windows并没有像oc平台这样好的抽象,但是实现起来其似乎也是差不多的思想,异步I/O消息通知的事件包括:FDREAD、FDWRITE、FDFORCEREAD、FDCONNECT、FDACCEPT、FDCLOSE这些,每个事件都相应的能通知到socket数据处理层就可以了。

比较下来两个系统平台对于TCP/IP异步socket IO的封装是差不多的,差别只是抽象的层次mac pro平台更加高一点,windows更加接近原生态的socket。 
以上讲的是利用各自平台的网络库实现与服务器之间通信的技术,接下来一起看下在内存中收发数据的两个buffer,因为数据传递是异步的,发送/接收数据都有可能是还没有真正发送/接收成功,所以需要在socket数据处理层维护两块buffer——inBuffer(接收数据缓存)/outBuffer(发送数据缓存)。以outBuffer(发送数据缓存)为例子,当你调用sendSocketData的时候,由于操作系统发送缓存区满了导致调用失败 ,由于是异步socket IO,系统的send过程并不会等待系统的发送缓存区空了再发送数据,而是会让send过程失败,等到系统的发送缓存区空的时候通过一个可写的事件通知你,所以在sendSocketData过程send失败的情况下,你所需要做的就是将数据缓存到outBuffer(发送数据缓存)中,等到可写事件收到了再将outBuffer(发送数据缓存)的数据发送出去,上个流程图吧:

5 业务模块拆分以及模块与模块之间通过接口交互

任何应用程序从业务角度讲都不是单一的,是由许多业务组装起来的(比如mac TT有登陆业务、文件传输业务、消息管理业务、会话管理业务等),那么这些业务需要如何有机的结合起来完成一个应用程序的所有需求呢?同学们应该会首先想到MVC(Model、View、Controller)/MVP(Model、View、Presenter),嗯没错,在OC平台中本身就是按照MVC来实现具体业务的开发的,DDLogic在MVC基础之上再加了一个Module的概念,为的是和前面:基于Task的任务调度、pdu通信协议以及拆装包过程、事件的订阅与发布、持久化数据以及基于此数据之上的一层数据监听机制(类似IDE工具调试的 Watch)这些有机的结合起来,回头看看是否还记得前面PDU协议面的moduleid和存储格式按照三元里面的moduleid呢?先上个简单的图吧:

 
DDLogic的思路是这样的(以登陆业务模块为例子):

 1.所有模块的对外接口都通过DDLogic Modules Manager来管理。
 2.模块与模块之间通过接口来调用,
模块内部实现对外不可见。比如外部只能调用DDloginModule的doLogin()来实现登陆操作,调用方是不知道具体如何实现登陆的。
 3.每个独立的业务创建成为业务module——DDLoginModule,有一个全局唯一的业务模块ID——MODULE_ID_LOGIN
 4.调用业务模块的接口函数通过全局唯一业务模块ID——MODULE_ID_LOGIN来,DDLoginModule*
loginModule = getDDModule(MODULE_ID_LOGIN);[loginModule doLogin];
 5.支持插件管理,n(n >=1)个模块合作来组装成1个插件,并且支持动态加载/卸载(未实现的目标)

是不感觉DDLogic框架连这种东西也拿出来分享,没啥技术含量是个程序员都知道用类似的方式来拆分业务?是的你的感觉是对的,但是只对了一半,确实看起来没啥营养,但是请你再往下看你会发觉这个点才是整个DDLigic框架的精髓,如果说上面讲的每个设计点是DDLogic框架的一条条河流的话,那么这里就应该是它们的汇聚地,下面逐个点来分析

 1.基于Task的任务调度:每个task的执行都会绑定一个module_id来知道具体是哪个模块的task在执行,并且通过module_id将任务执行的结果反馈给模块,这条河流就汇聚到module了。
 2.事件的订阅与发布:每个事件都是通过指定module_id和MKN来订阅的,等到被订阅事件发布的时候同样通过指定module_id和MKN来通知出去,这条河流也汇聚到moudule了
 3.pdu通信协议以及拆装包过程:通过解析pdu协议头获取module_id和command_id,然后生成NetworkTask派发到相应的模块中区,这条河流也汇聚到module了
 4.持久化数据以及基于此数据之上的一层数据监听机制(类似IDE工具调试的 Watch):通过储格式三元组[module_id,module_item,module_tag],这条河流也汇聚到module了

6 持久化存储以及基于此数据模型数据监听机制(类似IDE调试工具的Watch)

DDLogic数据持久化用的是NSCoder可以支持基于业务模块的数据序列化/反序列化。基于数据模型的监听机制(暂且称作data watch机制)对一个应用程序来说是非常实用的,举个例子:你的好友管理模块的数据新增了一个好友,好友列表数据发生add事件,监听此数据变化的模块如好友列表控件、消息管理模块等都会收到相应的通知并作出及时的处理。 
这块将放到《 
mac TT开发点点滴滴之四——NSCode与DDlogic的结合》中做深入阐述,敬请期待。

mac TeamTalk开发点点滴滴之一——DDLogic框架分解下

时间: 2024-08-11 07:47:20

mac TeamTalk开发点点滴滴之一——DDLogic框架分解下的相关文章

mac TeamTalk开发点点滴滴之一——DDLogic框架分解上

DDLogic框架着重解决如下这几个点: 基于Task的任务调度 事件的订阅与发布 pdu通信协议以及拆装包过程 基于WSAAsyncSelect模型的网络异步I/O TCP/IP长连接 业务模块拆分以及模块与模块之间通过接口交互 持久化数据以及基于此数据之上的一层数据监听机制(类似IDE工具调试的 Watch) 下面针对每个点分别做描述: 1 基于Task的任务调度(Task 调度) 任何应用程序都会存在一个个需要处理的业务,只有如此你的应用程序才是活的,才能完成用户的业务需求.这些任务或是后

mac TT开发点点滴滴之一——网络层重构

作者:独嘉   时间:2014-06-23 概述 为了增加程序的可扩展性,以及降低后期维护的成本,在MAC TT的开发后期,我决定重构TT的网络层. 重构之后的网络层实例化了网络请求,这样有一个好处就是方便维护网络请求的生命周期.每一个网络请求都把自己的数据打包和解包封装起来.换一种说法就是每个网络请求都是相互独立的.相对于之前把数据打包放在一个PackManager中,把解包的操作分发到UserModule和MessageModule等module中的做法更加解耦,后期想添加一种新的网络请求时

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)

iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角) 2015-04-05 15:25 2482人阅读 评论(1) 收藏 举报开源框架 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作.      下载:https://github.com/mwaterfall/MWPhotoBrowser目前比较活跃的社区仍旧是Github,

iOS开发-常用第三方开源框架介绍

iOS开发-常用第三方开源框架介绍 图像: 1.图片浏览控件MWPhotoBrowser 实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存.可对图片进行缩放等操作. 下载:https://github.com/mwaterfall/MWPhotoBrowser 目前比较活跃的社区仍旧是Github,除此以外也有一些不错的库散落在Google Code.SourceForge等地方.由于Github社区太过主流,这里主要介绍一下G

Android &amp;Swift iOS开发:语言与框架对比

转载自:http://www.infoq.com/cn/articles/from-android-to-swift-ios?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=articles_link&utm_content=link_text 从Android到Swift iOS开发:语言与框架对比 我从2009年开始做Android开发,开始接触Swift是在2014年底,当时组里曾经做过一个Demo App,感觉技术还

关于jsp商城开发中一些常用框架的介绍

Struts跟Tomcat.Turbine等诸多Apache项目一样,是开源软件,这是它的一大优点,使java商城产品以及jsp商城开发者能更深入的了解其内部实现机制.除此之外,在 java商城开发 中Struts的优点主要集中体现在两个方面:Taglib和页面导航.Taglib是Struts的标记库,比较灵活,能大大提高开发效率.另外,就目前国内的JSP开发者而言,除了使用JSP自带的常用标记外,很少开发自己的标记,或许Struts是一个很好的起点.struts历经6年多的发展,是目前用户数最

更换 mac时 开发证书

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 18.0px; font: 16.0px ".PingFang SC"; color: #2f2f2f; background-color: #ffffff } span.s1 { } span.s2 { font: 16.0px "Helvetica Neue" } 更换 mac时 开发证书,先导出, 后导入,如果出现错误,把projects自动签名改为手动

AppleWatch开发入门一——Watch的开发思路与应用框架

AppleWatch开发入门一--Watch的开发思路与应用框架 一.引言 Apple Watch无疑是apple在智能手表领域的一次革命,如何在Watch上开发出实用且具有美感的应用,是iOS开发者们开始思考的一个问题,由于watch的随身性和快捷性,在某些方面,它有比iphone更加大的优势,要抓住watch的这些特点,开发出淋漓尽致的应用,就需要改变一些在iphone开发的思路,正如一句话:只有忘掉经验,才会有意想不到的突破. 这一系列博客,首先是总结我在公司watch项目开发中的一些经验

Cocos2d-x--iOS平台lua加密成luac资源方法和Jsc文件&lt;MAC平台开发试用--windows平台暂未研究&gt;

    首先要说,最近真的是太忙了,好久没写博客了,今天正好有空,就写一下最近在写游戏中的一些发现: 话说,基于Cocos2dx 引擎 + 脚本写游戏,至今的感触就是可以进行增量更新和即时编译等,节省了很多时间:好了废话不多说了,进入正题: 这里我是以Cocos2d-x-2.2.2 为例<其实,写着文章时候Cocos2d-x-3.2 都封版了>: 今天我就说一下怎么用Cocos2d-x3.2中的cocos-console 去 批量 加密lua脚本-变成luac文件 ,js文件变成jsc加密文