绑定luasocket到cocos2d-x的lua的同步问题

  • 本帖最后由 pleasenter 于 2012-5-5 15:10 编辑 *

今天好不容易绑定了luasocket2.02到cocos2d-x0.12的版本,可是正准备开写的时候突然楞住了,如果我的lua游戏逻辑需要跟服务器交互,那么我在lua中创建了一个socket并连接到服务器后,每次的send,recv都是阻塞的,而我的界面代码又是lua在执行,这也就意味着每次send,recv的时候,游戏就将卡在那里,然后等send,recv执行完毕界面才能动,局域网还好,如果是广域网呢,这是不可接受的。在c++或者别的语言里,一般是新建一个thread来解决阻塞的问题,可是我们亲爱的Lua是不支持thread的,她所支持的协程只能用于非阻塞代码,所以绑定了luasocket到cocos2d-x的行为是愚蠢的,除非你的代码在局域网内运行。
之所以写到这里,是希望国内像我一样对c++不熟悉又打算用简单的Lua来写游戏的朋友不再犯我这样的错误,抛砖引玉。
上面光写了问题,还没写解决办法呢。这里也说说我的不成熟的想法,就像平时我们在别的语言里写网络程序一样,当你有IO操作不想阻塞掉用户界面的时候,就只能用异步IO或者开一个专门的线程来执行IO操作,最后在IO完成的时候再通知到界面代码,这里无疑也只能这样解决。你可以在cocos2d-x的主程序代码(c++)里面用一个线程封装好你的socket操作,然后在主线程里增加两个数据队列(发送和接收,要有同步锁),最后封装两个函数往里面塞数据和取数据,lua代码则起协程来调用这两个函数,这两个函数是不会阻塞的,所以lua操作的界面也不会阻塞。另外lua在每次调用完这些非阻塞的函数后,可以把调用协程挂起,而c++里处理完队列数据的发送接收后再唤醒协程,这样可以了。
上面只是一个思路,我没有验证的,大家可以试试。

可不可以在COCOS2D-X的c++代码 里面去开一线程做网络通信去执行通信的lua,再开一个单独的线程去做界面?

— Begin quote from ____

zitonglove 发表于 2012-4-21 12:00 url

可不可以在COCOS2D-X的c++代码 里面去开一线程做网络通信去执行通信的lua,再开一个单独的线程去做界面? …

— End quote

我也是这么想的。不知道可不可以。

界面本身就是用的c++主线程,你应该在c++里开一个socket专用线程,然后io做完了就写到某个数据里,在Lua的schedule里去查看数据是否来了,有数据就处理。

以前是把 llthreads 放到 cocos2d-x 仓库中的,但后来考虑到保持 cocos2d-x 的单纯,所以又去掉了。现在自己下载集成即可。

llthreads 是别人开发的 lua 模块,下载地址: https://github.com/Neopallium/lua-llthreads 。我自己使用是很稳定的,还没发现问题。
不过我也打算再尝试一下 LuaLanes (https://github.com/LuaLanes/lanes) 模块,感觉这个模块功能更多,而且更新更活跃。

你说的长连接应该是开个独立的线程来维护连接,并通过某种渠道和主线程交换数据。
你可以参考 lua-zmq 的做法来实现(https://github.com/Neopallium/lua-zmq)。
LuaLanes 提供了更简单的线程间通讯功能,也可以试试看。


以前的回复复制过来。楼主顺便把帖子标题改改吧,会误导其他用户。

  • 本帖最后由 pleasenter 于 2012-5-5 15:14 编辑 *

已经改好了,谢谢。

这几天试着跑了跑luasocket,其实他有个settimeout函数,设置为0的超时就不会阻塞了,看了还是自己对socket研究的不够深入,误导大家了,正在跑luasocket,通了再贴点代码上来供大家参考。

不知道luasocket的recv阻塞问题怎么解决的,求指教,490401821,希望得到您的帮助