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 = socketend |
--发送数据给服务器
|
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-- readDatafunction 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