cocos2dx上的通用socket通信(一)

前言:之前一直在捣鼓socket通信模块,当然,到现在为止我还没有彻底弄好,不过数据至少是有去有回了,只是在Android上跑容易崩掉罢了,汗。在网上找了好多关于cocos2dx上跨平台的socket通信库的文章,都只有皮毛,不见有真正好用的,好吧,我确实比较懒,当然,官方没有去实现这个定有它的原因,我也懒得深究,因为最近折腾Android上的坑都快把我搞崩溃了。希望这个能搞个系列吧,我有好多文章标题上有(一)之类的,后面再也没出现过(二),不是懒得写就是试验失败,不能继续了。这里是我和某人(暂时不便透露)之间的一封邮件内容(其实是我写的),我做了摘取,算是个思路的整理过程吧,后续我会把对应的代码也放上来。

目的

    在cocos2dx上实现一个支持异步通讯的socket通信例子。

 大致思路

  1. 专门实现一个业务处理模块,比如叫TransactionModule,其中封装了BSD的socket进行数据的收发。提供单例实现,即提供静态的方法访问一个全局的唯一对象。
  2. 所有的数据发送都是通过业务模块处理,比如提供一个SendData之类的函数。
  3. 业务处理模块独立启动一个线程(使用pthread)用来接收服务器发来的数据,放到TransactionModule中的数据接收缓存。当有数据写入缓存时(或者当有数据收到时),通知界面线程取数据后更新界面。

 问题

    这里犯了错误,直到昨天我才对这个错误有比较深刻的认识:

  1. 工作线程不能操作界面线程的资源,比如更新界面数据,不要在工作线程中回调涉及界面更新的函数
  2. CCNotificationCenter并不是线程安全的(这样讲可能不是很准确),如果在工作线程中post,那必然回调函数还在工作线程中响应
  3. 线程间的通讯,还是需要用一个线程安全的队列或者线程安全的数据交换区来实现,比如可以使用pthread_mutex_lock和pthread_mutex_unlock之类的方法来实现线程间访问数据的互斥

 实现方法更新

    对应的业务模块TransactionModule依然存在,启动工作线程的方式也不改变,本来在工作线程中收到数据后使用CCNotificationCenter去实现对应业务处理的回调函数不在工作线程中使用,可以考虑放到主线程(界面线程)中使用,这样可以使得处理逻辑更加清晰。

  • 步骤一:在TransactionModule中有业务请求时,检查是否有连上服务器,没有链接上则执行步骤二,如果链接状态正常,则执行步骤三
  • 步骤二:创建Socket,链接服务器,如果链接成功,则执行步骤三,如果链接失败则报错,请求失败,结束
  • 步骤三:发请求数据到服务器,判断send返回状态,如果小于0,执行步骤四,如果已发送长度等于发送长度,则执行步骤五,否则继续执行步骤三再次发送剩余数据(这里没有考虑等于0的状态)
  • 步骤四:返回了SOCKET_ERROR错误,关闭socket,重置链接状态和创建Socket状态,返回错误,请求失败,结束
  • 步骤五:检查接收线程是否启动,如果线程正在运行,则执行步骤七,否则执行步骤六
  • 步骤六:创建线程,判断停止标志,循环执行接收数据函数(使用libevent的话,仅仅是执行dispatch),然后转到步骤七,等待数据返回。
  • 步骤七:等待服务器数据返回,阻塞状态,如果有数据返回,则执行步骤八
  • 步骤八:当有数据到达时,判断接收状态,如果大于等于0,则执行步骤四,并设置线程终止标志。否则把数据添加到公共缓冲区或者公共队列(线程安全)中。

    以上便是业务处理模块在收发数据时要做的事情,并且从步骤五开始,都是工作线程调用的函数(仅由工作线程调用)。步骤四有主线程调用或者工作线程调用处理。呃,如果有个流程图会更直观得解释下处理步骤,暂时我手边没有绘制流程图的工具,抱歉。

    在界面线程(主线程)中,会启动一个定时器,用于判断公共缓冲区或者公共队列中是否有未处理的数据到达。如果有则调用业务处理模块的数据预处理函数处理数据(比如处理粘包之类),处理完成后调用界面的函数来更新数据,做场景跳转等。

    这里的关键应该就是工作线程只处理数据的返回,并且把返回数据放到公共缓冲区中,其余的就什么都不干。界面线程单独用定时器去处理缓冲区中的数据。其实就是线程间的数据通信。

    另:这里我使用的通信事件处理是libevent,socket的处理是用的是ODSocket,这个是针对WIN32和其余*unix平台做了一个简单封装。这样就可以在win32、android、iOS上实现统一的socket通信处理了。当然libevent是要各个平台分别编译的。

    到了主线程中,当数据处理的时候,倒是可以使用CCNotificationCenter来实现回调函数来处理。之前一直以为CCNotificationCenter是相对独立的线程中的实现,并且可以通知到各个其他线程实现正确的函数回调,这明显是天真了,因为函数是不会绑定线程执行的,除非另外有一个机制去保证某些函数的回调只实现在绑定的线程中(扯远了)。


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值