[Unity热更新]tolua# & LuaFramework(六):网络通信

inez98077426819 云计算/大数据 5 次浏览 没有评论

一.客户端

AppConst:设置要连接的服务器IP地址和端口号,当要测试更新时,默认使用的是WebUrl

SocketClient

成员:

NetworkStream outStream:负责输出

MemoryStream memStream:负责接收,存储所有接收到的信息

BinaryReader reader:对MemoryStream中的信息进行读取

byte[] byteBuffer:暂存接收到的信息

方法:

void OnReceive(byte[] bytes, int length) :将暂存的信息写入到memStream的末端,然后尝试读取信息,先读取两个字节(信息头,表示该条信息的长度),判断长度,如果能读到一条完整的信息,则将该完整信息交给NetworkManager(以KeyValuePair<int, ByteBuffer>的方式,其中key为消息类型,value为协议类型 + 消息内容),由NetworkManager进行处理,此时NetworkManager会逐条从队列中读取信息,然后交给SocketCommand进行处理,SocketCommand会调用Network.lua中的OnSocket进行处理,传入消息类型和数据,最终消息会在lua中分发。因此,我们可以在lua中写逻辑来发送或者接受信息,因为逻辑使用lua来写的,所以灵活性就很高了。

这里的消息类型是什么呢?以自带例子为例:

客户端protocal.lua

Protocal = {  Connect  = '101'; --连接服务器  Exception   = '102'; --异常掉线  Disconnect  = '103'; --正常断线     Message  = '104'; --接收消息 }

服务器端Protocal.cs

        public enum Protocal {         //Buildin Table         Connect           = 101, //连接服务器         Exception         = 102, //异常掉线         Disconnect        = 103, //正常断线            Login      = 104, //登录游戏         Quit              = 105, //离开游戏         ServerTime        = 106, //服务器时间         HeartBeat         = 107, //心跳数据          //Socket Request Table         Chat              = 1001,   //User Chat         Friend            = 1002,   //Friend         Mail              = 1003,   //Mail         PK                = 1004,   //PK         Join              = 1005,   //ComeIn         PayBack           = 1006,   //支付消息          //Webclient Request Table         Register          = 2001,   //注册请求         UserInfo          = 2002,   //用户信息         Buy               = 2003,   //购买         Sell              = 2004,   //卖掉         RoleList          = 2005,   //角色列表         ServerList        = 2006,   //服务器列表     }

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

现在梳理一下流程:

1.首先找到Game.lua中的OnInitOK,通过networkMgr:SendConnect();进行连接,然后追踪到SocketClient.cs中的ConnectServer,当连接成功时会回调OnConnect,通过NetworkManager.AddEvent(Protocal.Connect, new ByteBuffer());,把Protocal.Connect作为key放入消息队列中,由Network.lua中的OnSocket进行处理。

而由于Network.lua中的Start方法,通过Event.AddListener(Protocal.Connect, this.OnConnect);得知,最后会输出”Game Server connected!!”

[Unity热更新]tolua# & LuaFramework(六):网络通信

2.先成功运行一下框架自带例子,如无意外,右下方会出现这个,点击这个按钮后会发生什么呢?

[Unity热更新]tolua# & LuaFramework(六):网络通信

找到PromptCtrl.lua中的OnClick,它会对TestProtoType进行判断(其实就是看选择的是什么协议)。找到define.lua,发现框架默认的是TestProtoType = ProtocalType.BINARY;那么好了,回到PromptCtrl.lua,就可以知道当点击按钮后,TestSendBinary就会执行,发送二进制。发送消息类型Protocal.Message,即104,然后服务器端收到了这个104后,通过反射转化为104对应的Login类,消息内容就由Login类进行处理。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public void SendMessage(ByteBuffer buffer):对外接口,先写入信息长度,再写入信息。

NetworkManager

对SocketClient的进一步封装,持有一个网络信息队列。同时与Network.lua进行交互。

define.lua:可以设置当前使用的协议类型。这里的协议类型,指的是BINARY、PB_LUA、PBC、SPROTO这四种。

protocal.lua:可以设置传递的消息类型。

Network.lua:管理lua中的网络部分,其中Network.OnMessage(buffer)是对接受信息的处理。在lua中,可以使用networkMgr:SendMessage(buffer);发送信息,具体用法可以看PromptCtrl.lua,它是先写入消息类型,然后是协议类型,最后就是消息内容了。

即:消息 = 消息总长度(两字节) + 消息类型(两字节) + 协议类型(一字节) + 消息内容

Game.lua:找到function Game.OnInitOK(),这里就可以看到要连接的ip地址以及端口号了。真正进行网络连接的是networkMgr:SendConnect();这句话,而不是在c#中进行连接的。



二.服务器端

GameServer:入口文件

Protocal:定义消息类型和协议类型

SocketUtil:

方法:

public static void SendMessage(ClientSession session, Protocal protocal, ByteBuffer buffer):发送消息时,先写入消息的总长度(ushort,两字节),然后是消息的类型(ushort,两字节),最后是消息体( 协议类型 + 消息内容)。

public void OnRequestReceived(ClientSession session, BinaryRequestInfo requestInfo):先ReadShort得到消息的类型,然后将该类型转换为一个类(具体看Message文件夹),然后将这条消息传递给那个类,例子里面是Login这个类,然后会根据协议类型和消息内容反馈给客户端。这里你会看到,从客户端传过来的消息还包含这条消息的长度,但并没有看到其处理,这是因为SuperSocket已经帮我们处理好了,你可以找到ClientReceiveFilter这个类,它继承自FixedHeaderReceiveFilter,即固定消息头,并且使用了base(2)进行初始化,即是指每条从客户端传递过来的消息,SuperSocket都会把前两个字节读取出来,得到消息的长度,然后把剩余的完整的内容反馈给我们(通过requestInfo.Body),显然地SuperSocket肯定帮我们处理好了粘包半包的问题了。

运行结果:

[Unity热更新]tolua# & LuaFramework(六):网络通信

[Unity热更新]tolua# & LuaFramework(六):网络通信

三.结合pblua

修改一下define.lua:TestProtoType = ProtocalType.PB_LUA;

.proto:

message LoginRequest {  required int32 id = 1;  required string name = 2;  optional string email = 3; }  message LoginResponse {  required int32 id = 1; }

发送:

    local login = login_pb.LoginRequest();     login.id = 2000;     login.name = 'game';     login.email = 'jarjin@163.com';     local msg = login:SerializeToString();     ----------------------------------------------------------------     local buffer = ByteBuffer.New();     buffer:WriteShort(Protocal.Message);     buffer:WriteByte(ProtocalType.PB_LUA);     buffer:WriteBuffer(msg);     networkMgr:SendMessage(buffer);

local protocal = buffer:ReadByte(); local data = buffer:ReadBuffer();  local msg = login_pb.LoginResponse(); msg:ParseFromString(data);

上面所说的是客户端的,服务器端也有.proto以及对应的.cs,也是差不多的操作

四种协议:http://doc.ulua.org/article/ngui/simpleframework_base4.html

内容如有侵犯你的权益,请联系删除

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Go