您的位置:首页 > 理论基础 > 计算机网络

Cocos2d-x开发网络游戏(四) 处理网络线程

2013-08-21 15:05 295 查看
原文链接:http://blog.sina.com.cn/s/blog_6084f58801014g0g.html

由于socketcc只开放了以阻塞的形式接收网络数据,所以为避免界面卡死,我们只能选择开线程的方式。其实即使以非阻塞的形式接收网络数据,我们通常也要以开线程的形式来处理网络数据。

既然处理网络数据要开线程,那么我们的网络线程要开在哪里呢?2dx的创始人walzer给出的建议是开在appDelegate中。那么接收到网络数据,分包处理后(关于数据接收,分包可以参考上一篇文章)引出的界面更新问题我们如何去处理,由于界面的更新不能放到线程里去处理,我们要做的是如何把子线程接收处理后的数据放到主线程去更新。这里给出一种思路:客户端网络线程接收包处理后将其封装成事件然后加入事件队列,当然队列封装成什么样子要看你自己处理。然后在主线程中取出队列事件命令进行界面的更新。

下面是实现思路:

1. 实现公共消息处理类:此类继承自CCNode,用于主线成界面更新。公共消息处理类用于处理公共消息,也就是处理可能在任何场景都会进行界面更新的消息。比如服务器发送消息要求客户端不论在那个场景都要弹出提示框的命令等。特定场景的消息的处理放到特定场景即可,不再赘述。

class CCQuene;

class NetPackage;

class PublicMsgHandler:public cocos2d::CCNode {

private:

CCQuene * _eventQuene;

private:

MutualExclusion mutexQuene;

pid_t pidMutExOwner;

void WaitMutex() { mutexQuene.Lock(); pidMutExOwner = getpid(); }

void ClearMutex() { mutexQuene.Unlock(); }

public:

PublicMsgHandler();

~PublicMsgHandler();

virtual void update(float fDelta);

void addEvent(NetPackage * netPackage);

};

来看里面的实现:

PublicMsgHandler::PublicMsgHandler(){

_eventQuene=new CCQuene();

this->onEnter();

this->onEnterTransitionDidFinish();

this->scheduleUpdate();

}

PublicMsgHandler::~PublicMsgHandler(){

this->unscheduleUpdate();

delete _eventQuene;

}

void PublicMsgHandler::update(float fDelta){

WaitMutex();

if (_eventQuene->count()>0) {

NetPackage * package=(NetPackage *)_eventQuene->popObject();

switch (package->type) {

default:{

CCLog("public events");

}

break;

}

package->release();

}

ClearMutex();

}

void PublicMsgHandler::addEvent(NetPackage * netPackage){

WaitMutex();

_eventQuene->pushObject(netPackage);

ClearMutex();

}

需要注意的是这里使用了资源锁,因为_eventQuene在不同线程执行时很可能发生同时访问,这是如果没有处理,将直接导致崩溃。关于信号量有什么不接大家可以参考操作系统。

在update中我们添加事件处理。如界面更新等。

在接收线程中接收封装NetPackage,然后将其扔进队列

2. 如何在appDelegate中实现主线程的界面更新。

我们知道CCNode中实现了update方法,CCNode在调用schedualUpdate后可以实现update调用,当注意有前提,此CCNode必须处于running状态。默认情况下节点加入父节点后就会自动处于running状态。不过可以的是AppDelegate不是继承自CCNode,这样我们就没有办法在此调用update方法。那么那些共有消息如何处理。

别急,有办法。看下PublicMsgHandler的构造函数

PublicMsgHandler::PublicMsgHandler(){

_eventQuene=new CCQuene();

this->onEnter();

this->onEnterTransitionDidFinish();

this->scheduleUpdate();

}

在构造函数中我们调用了

this->onEnter();

this->onEnterTransitionDidFinish();

只要调用这两个方法节点就可以处于运行状态。

3. 使AppDelegate保有PublicMsgHandler

bool AppDelegate::applicationDidFinishLaunching()

{

pMsgHandler=new PublicMsgHandler();

。。。。。。

。。。。

}

ok,这样游戏就可以接收公共消息并可以实现主线成的更新。对于相应页面的消息处理,你可以同样按PublicMsgHandler的处理方式去处理。

就介绍到这了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: