Quick-Cocos2d-x v3.3里面提供了两种长连接WebSockets、SocketTCP,这里说一下SocketTCP的用法。

1
2
3
local net = require("framework.cc.net.init")
local ByteArray = require("framework.cc.utils.ByteArray")
require("framework.cc.utils.bit")

-- 网络初始化,添加侦听函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function scnet.init(  )
local time = net.SocketTCP.getTime()
print("socket time:" .. time)
  
local socket = net.SocketTCP.new()
socket:setName("HeroGameTcp")
socket:setTickTime(1)
socket:setReconnTime(6)
socket:setConnFailTime(4)
socket:addEventListener(net.SocketTCP.EVENT_DATA, scnet.receive)
socket:addEventListener(net.SocketTCP.EVENT_CLOSE, scnet.tcpClose)
socket:addEventListener(net.SocketTCP.EVENT_CLOSED, scnet.tcpClosed)
socket:addEventListener(net.SocketTCP.EVENT_CONNECTED, scnet.tcpConnected)
socket:addEventListener(net.SocketTCP.EVENT_CONNECT_FAILURE, scnet.error)
scnet.socket = socket
end

--发送数据给服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function scnet.send( msgid,data )
 --  encodeData 此方法是根据需要发送的数据安装与服务器定义好的消息格式去write
 local _ba = scnet.encodeData(msgid,data)
 print("scnet.send _ba",_ba:getLen())
 if not _ba then 
 print("发送数据出错了.......",msgid)
   return 
 end
 _ba:setPos(1)
 local byteList = {}
 local byteCount = 0
 --  把数据读出来,加密
 for i=1,#_ba._buf do
 local tmpBit = string.byte(_ba:readRawByte())
 byteCount = byteCount + tmpBit
 tmpBit = bit.band(tmpBit + 80,255)
 tmpBit = bit.band(bit.bnot(bit.band(tmpBit,255)),255)
 byteList<i> = tmpBit
 end
 byteCount = byteCount % 256
 -- 最后再组成一个新的ByteArray
 local result = ByteArray.new(ByteArray.ENDIAN_BIG)
 result:writeShort(_ba:getLen() + 3)
 result:writeByte(byteCount)
 for i=1,#byteList do
 result:writeByte(byteList<i>)
 end
 -- 把数据发送给服务器
 scnet.socket:send(result:getPack())
end

-- 根据messageid来确定数据格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function scnet.encodeData( msgid,data )
 if msgid then
 local ba = ByteArray.new(ByteArray.ENDIAN_BIG)
 local fmt = InfoUtil:getMsgFmt(msgid)  -- 此处为读取消息格式 看下面的MessageType里面会有定义
 ba:writeStringUShort("token")  -- 此处为用户token,没有就为"",此处可以判断用户是否重新登陆啊等等.......
 for i=1,#fmt do
 scnet.writeData(ba,fmt<i>,data)
 end
 local baLength = ba:getLen()
 local bt = ByteArray.new(ByteArray.ENDIAN_BIG)
 bt:writeShort(baLength + 4)   -- 2为message length  2为message type
 bt:writeShort(msgid)
 bt:writeBytes(ba)
 return bt
 end
end

-- write 数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function scnet.writeData( ba,msg_type,data )
   
 local key = msg_type.key
 print("scnet.writeData","key",key)
 if key and data[key] then
 local _type = msg_type["fmt"]
 if type(_type) == "string" then
 if _type == "string" then
 ba:writeStringUShort(data[key])
 elseif _type == "number" then
 ba:writeLuaNumber(data[key])
 elseif _type == "int" then
 ba:writeInt(data[key])
 elseif _type == "short" then
 ba:writeShort(data[key])
 end
 else
 ba:writeShort(#data[key])
 for k,v in pairs(data[key]) do
 for i=1,#_type do
 scnet.writeData(ba,_type<i>,v)
 end
 end
 end
 else
 print("找不到对应的 key",msg_type.key,msg_type,data)
 end
end

-- 读取数据

-- 接收消息

1
2
3
4
5
6
7
8
9
10
11
12
function scnet.receive( event )
 local ba = ByteArray.new(ByteArray.ENDIAN_BIG)
 ba:writeBuf(event.data)
 ba:setPos(1)
--  有连包的情况,所以要读取数据
 while ba:getAvailable() <= ba:getLen() do 
 scnet.decodeData(ba)
 if ba:getAvailable() == 0 then
 break
 end
 end
end

-- 消息数据解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function scnet.decodeData( ba )
 local len = ba:readShort() -- 读数据总长度
 local total = ba:readByte() -- 一个用于验证的数子
 local byteList = {}
 local tmpTotal = 0
 for i=1,len - 3 do  -- 去除前两个长度
 local tmpBit = ba:readByte()
 local enByte = scnet.decodeByte(tmpBit)
 tmpTotal = tmpTotal + enByte
 byteList<i> = enByte
 end
  
  
 local result = ByteArray.new(ByteArray.ENDIAN_BIG)
 for i=1,#byteList do
 result:writeRawByte(string.char(byteList<i>))
 end
 result:setPos(1)
 if (tmpTotal % 256) == total then
 scnet.decodeMsg(result)
 else
 print("scnet.decodeData  total   error")
 end
end

-- 根据格式解析数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function scnet.decodeMsg( byteArray )
 local rData = {}
 local len = byteArray:readShort()
 local msgid = byteArray:readShort()
 local roleString = byteArray:readStringUShort()
 local fmt = InfoUtil:getMsgFmt(msgid)
 for i=1,#fmt do
 scnet.readData(byteArray,fmt<i>,rData)
 end
 if rData["result"] ~= 0 then
 print("result  handler is here  ",rData[key])
 return
 else
 NetManager:receiveMsg(msgid,rData)
 end
end
-- readData
function scnet.readData( ba,msg_type,data)
 local key = msg_type.key
 if key then
 data[key] = data[key] or {}
 local _type = msg_type["fmt"]
 if type(_type) == "string" then
 if _type == "string" then
 data[key] = ba:readStringUShort()
 elseif _type == "number" then
 data[key] = ba:readLuaNumber()
 elseif _type == "int" then
 data[key] = ba:readInt()
 elseif _type == "short" then
 data[key] = ba:readShort()
 end
  
  
 if key == "result" then  -- 当结果不为零的时候,说明有错误
   
 if data[key] ~= 0 then
 print("result  handler is here  ",data[key])
 return
 end
 end
  
  
 else
 local _len = ba:readShort() -- 读取数组长度
 for i=1,_len do
 local tmp = {}
 for j=1,#_type do
 scnet.readData(ba,_type[j],tmp)
 end
 table.insert(data[key],tmp)
 end
   
 end
 else
 print("找不到对应的 key  scnet.readData",msg_type.key,msg_type,data)
 end
end

-- 数据解密

1
2
3
4
5
function scnet.decodeByte( byte )
 local tmp = bit.band(bit.bnot(bit.band(byte,255)),255)
 tmp = bit.band((tmp + 256 - 80),255)
 return tmp
end

消息格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
-- 发送
MsgFmt["1001"] = {
 {
 key = "list",
 fmt = {
 
 key = "id",fmt = "int"
 },
 
 key = "name",fmt = "string"
 },
 
 key = "level",fmt = "int"
 },
 
 key = "sex",fmt = "int"
 }
 }
 },
 {
 key = "userid",fmt = "int"
 }
}
--  返回
MsgFmt["5001"] = {
 {
 key = "result",fmt = "int" 
 },
 {
 key = "list",
 fmt = {
 
 key = "id",fmt = "int"
 },
 
 key = "name",fmt = "string"
 },
 
 key = "level",fmt = "int"
 },
 
 key = "sex",fmt = "int"
 }
 }
 }
}

网络管理NetManager

管理网络的发送与接收

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
-- 初始化
function NetManager:init(  )
 self._listenerList = {}
 scnet.init()
 scnet.connect(host,port)
end
  
-- 注册消息
-- 注册之后 接受到服务器消息之后进行广播,谁注册,谁相应
function NetManager:registerMsg( msgid,callBack )
 self._listenerList[msgid] = self._listenerList[msgid] or {}
 local isExist = self:findCallBack(msgid,callBack)
 if not isExist then
 table.insert(self._listenerList[msgid],callBack)
 end
end
  
  
  
-- 移除注册消息
function NetManager:removeRegister( msgid,callBack )
 if self._listenerList[msgid] then
 for k,v in pairs(self._listenerList) do
 if v == callBack then
 self._listenerList[msgid][k] = nil
 end
 end
 end
end
  
  
  
-- 发送消息
-- 整理数据发送给服务器
function NetManager:sendMsg( msgid,data )
 scnet.send(msgid,data)
end
  
  
  
-- 接受消息
-- 派发事件(数据)
function NetManager:receiveMsg( msgid,data )
 if self._listenerList[msgid] then
 for k,v in pairs(self._listenerList[msgid]) do
 v(data)
 end
 end
end
  
  
function NetManager:findCallBack( msgid,callBack )
 for k,v in pairs(self._listenerList[msgid]) do
 if v == callBack then
 return true
 end
 end
 return false
end

test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 监听事件
function MainScene:onEnter()
 NetManager:registerMsg(MsgType.SC_LOGIN ,handler(self,self.receiveHandler))
end
  
-- 移除坚挺
function MainScene:onExit()
    NetManager:removeRegister(MsgType.SC_LOGIN ,handler(self,self.receiveHandler))
end
 
-- 发送数据,根据MsgFmt构造数据
 local data = {}
  data.list = {}
  table.insert(data.list,{id = 1001,name = "小房",level = 1,sex = 1})
  table.insert(data.list,{id = 1002,name = "小田",level = 11,sex = 2})
  table.insert(data.list,{id = 1003,name = "2222",level = 21,sex = 1})
  table.insert(data.list,{id = 1004,name = "3333",level = 31,sex = 2})
  data.userid = 10001
  NetManager:sendMsg(MsgType.CS_LOGIN,data)

 

http://cn.cocos2d-x.org/tutorial/show?id=2604

http://zengrong.net/post/2020.htm

Quick-cocos2d-x v3.3 SocketTCP链接(转)的更多相关文章

  1. 转载+自练(莫喷)怎样在cocos2d 2.1.4里面使用动画和Texture Packer

    本文实践自 Ray Wenderlich.Tony Dahbura 的文章<How to Use Animations and Sprite Sheets in Cocos2D 2.X>, ...

  2. Cocos2D中Action的进阶使用技巧(二)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上回说到解决办法是使用CCTargetedAction类. C ...

  3. Google map API V3

    本文主要总结Google map API V3使用中最简单也是最常见的一些操作以及相关概念,如果需要更加详细的信息,请直接阅读Google提供的关于map的文档. google map api v3文 ...

  4. 【Q2D】如何导出自定义C++类给框架使用

    本文基于Quick cocos2d x这个游戏框架,为了行文流畅,后面都简称Q2D 导出自定义c++类给项目使用已经有了现成的例子了 详见:http://quick.cocos.org/?p=235 ...

  5. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q52-Q55)

    Question 52You are responsible for rebranding the My Sites section of a corporate SharePoint 2010 fa ...

  6. 嵌入式设备上的 Linux 系统开发

    转载:http://www.ibm.com/developerworks/cn/linux/embed/embdev/index.html   如果您刚接触嵌入式开发,那么大量可用的引导装载程序(bo ...

  7. OpenStack基础组件安装keystone身份认证服务

    域名解析 vim /etc/hosts 192.168.245.172 controller01 192.168.245.171 controller02 192.168.245.173 contro ...

  8. mui扩展字体在哪里下载

    一次在一个知名前端模板网站上用积分下载了一个手机网页模板,没想到作者竟然玩起了删减隐藏,故意挖坑. 查看其原因是少一个mui.ttf的文件,纵然其他的文件及名称都有删改但无关紧要.也就是好多人搜索的m ...

  9. 总结界面框架_UI_Adapter

    本人定期更新经典案例及解决方案如有疑问请联系我QQ1822282728 -- 277627117   下面是常用到的ui  Demo 安卓三级筛选菜单listview(非常经典) http://dow ...

随机推荐

  1. Swagger简介

    前言 Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件.本文简单介绍了在项目中集成swagger的方法和一些常见问题.如果想深入分析项目源码,了解更多内容,见参考资料. S ...

  2. Http错误 404.3-Not Found....或者500.19 Internal Server Error

    解决方法:以管理员身份打开VS2010x64位兼容命令提示:aspnet_regiis -i

  3. Wcf Restful Service服务搭建

    目的 使用Wcf(C#)搭建一个Restful Service 背景 最近接到一个项目,客户要求使用Restful 方式接收到数据,并对数据提供对数据的统计显示功能,简单是简单,但必须要使用Restf ...

  4. Azure 负载均衡和可用性集

    首先要2台以上的虚拟机,一开始我找了好久都没找到如何在一个云服务里添加多个虚拟机. 因为我使用的是快速创建,快速创建的界面是要新建一个云服务的,如果你输入现有的云服务名字,它会提示你重名了. 你要用[ ...

  5. Undefined symbols “_OBJC_CLASS_$_XXX” 问题

    解决方法是点击工程,在targets界面中找到Build Phases,根据提示信息“XXX”来判断缺少什么文件,一般如果缺少自定义的文件,XXX会是缺少的类名,那么就在Complie Sources ...

  6. 树形DP+二分(Information Disturbing HDU3586)

    题意:给出一颗数,1结点代表司令部,叶子节点代表前线,边全值代表花费,然后需要在某些边放置一些炸弹,炸弹的能量不能小于该边的费用,且炸掉的总费用不能超过m问炸弹能力最小多少, 分析dfs+二分,二分枚 ...

  7. [转]30分钟学会反向Ajax

    原文链接:http://www.cnblogs.com/learnhow/p/5708364.html 场景1:当有新邮件的时候,网页自动弹出提示信息而无需用户手动的刷新收件箱. 场景2:当用户的手机 ...

  8. 活动组件(三):Intent

    大多数的安卓应用都不止一个Activity,而是有多个Activity.但是点击应用图标的时候,只会进入应用的主活动. 因此,前面我已经建立了一个主活动了,名字是myActivity,现在我再建立一个 ...

  9. php js表单登陆验证

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. nginx、fastCGI、php-fpm关系梳理(转载 http://blog.sina.com.cn/s/blog_6df9fbe30102v57y.html)

        前言: Linux下搭建nginx+php+memached(LPMN)的时候,nginx.conf中配需要配置fastCGI,php需要安装 php-fpm扩展并启动php-fpm守护进程, ...