Ulua热更新提高 <三> 网络通信和ProtocolBuffer

原创   


说实话,ProtocolBuffer这个东西以前一直在用,很多公司在用。找了网上很多教程,在ULUA里怎么用,很少有讲到的。首先,分析一下,既然要热更新,那么协议最好也是能更新的,那肯定不能写C#协议,所以要用LUA能认识的东西,在框架Lua/3rd/插件包里,pbc,pblua,sproto,这3个都可以给LUA来使用的。pbc,是需要将proto文件转为pb文件,然后到LUA里去使用,我以前的公司用的这种办法。pblua,直接可以把proto转成一个Lua脚本,然后给Lua调用。sproto,看了下是直接用LUA写的协议。上面3个具体怎么用看官方例子,很详细。

流程是这样的,一般协议是服务端写好了proto文件,然后我们拿到手把它转成pb文件,拿到LUA里去用,使用ProtocolBuffer的好处就体现出来,服务器那么可能是JAVA的,C++的,我们不用管,服务器那边也有方案处理proto协议,客户端处理好proto协议就行了,两边只需要写一份通用协议就行了,而且数据序列化,解析数据,ProtocolBuffer也做好了,而且比Json需要的流量更小,因为是二进制的,但是由于不方便人阅读,网站还是用JSON的比较多,客户端用ProtocolBuffer,官网的probocol buffers并不支持lua,所以要用上面3个方法之一,来实现protobuf对lua的支持,说实话我现在还没搞懂pb文件到底是个什么东西,为什么必须做成pb文件,以后研究到了再更新,因为pbc不需要生成lua协议描述文件(比如login_pb),一个pb二进制文件就行了,比较简洁效率据说比pbLua高,所以用pbc。


框架官方网络通信的介绍:http://doc.ulua.org/article/ngui/simpleframework_base4.html

ProtocolBuffer相关博客教程:           

https://my.oschina.net/sniperLi/blog/530013    

http://blog.csdn.net/u014308482/article/details/52958148  

http://blog.csdn.net/linshuhe1/article/details/51781749


一. 制作Pb文件


1.  ProtocolBuffer  我们不需要源码,直接拿来用,下载地址 :https://github.com/google/protobuf/releases  下载其中的protoc-3.1.0-win32.zip  

2.解压后将  protoc.exe 复制到 C:\Windows\System32

3.protoc用法,打开CMD---输入   

  protoc -h 可以查看protoc的帮助

  proto 文件编译到Java文件: protoc -I=D:\   --java_out=D:\   D:\person.proto    (  protoc -I=源地址 --输出格式_out=目标地址  源地址/xxx.proto )

  proto 文件编译到pb文件:  protoc  -I=D:\   --descriptor_set_out=D:\addressbook.pb D:\addressbook.proto

4.这里直接用Proto文件生成pd文件,需要自己先创建个文本,改成pb后缀,然后再执行上面的命令,这里有可能我的做法不对,不可能这么弱智,非得自己先建一个,但是我找了半天不知道用什么方法。


二.网络连接

网络这一块发现有2篇不错的博客:http://blog.csdn.net/lyh916/article/details/51096463           http://blog.csdn.net/lyh916/article/details/51250924

讲的是LuaFramework,稍微有点不一样,但原理是一样的,讲的很好。

我写一下我自己的理解:

网络连接这块代码,C#代码主要是在Scripts/Network里面,外加一个NetworkManager.cs,Define修改ProtocalType协议类型,服务器消息处理 Network.lua ,消息类型protocal.lua。

连接到到服务器后 SocketCommand.cs会调用Network.lua的OnSocket方法,讲服务器的消息发送给Network模块。然后再添加消息监听AddListener和回调函数。(SocketCommand里也可以再添加C#的消息接受)

测试可以用官方提供的一个服务器源码,也是C#的。


1.连接服务器

在GameManager.lua里有详细的例子。

    AppConst.SocketPort = 2016;
    AppConst.SocketAddress = "192.168.1.188";
    NetManager:SendConnect();


2.给服务器发送消息

最底层在在SocketClient类里的 WriteMessage方法向NetworkStream写入byte数组。

一个完整的消息的byte[]包= 消息总长度(ushort两字节) + Protocal消息类型(ushort两字节) + ProtocalType协议类型(byte一字节) + 消息内容(WriteBuffer里写入的byte[])     

而且写入的顺序不能换,因为这个官方的服务器就是按照这个字节顺序来读取的。当然可以和服务器协商,看怎么设计消息包的结构。

测试服务端的话,就用官方提高的服务端,服务端在哪下载,怎么配置具体看上一篇博客。

需要修改SuperSocket.SocketService.exe.config配置文件,指定IP和端口号。(注意不要和HttpServer的资源下载端口相同)

<server name="GameService" serverTypeName="GameManagerService" ip="192.168.1.188" port="2016" maxConnectionNumber="1000"></server>


【Lua发送】 

    local buffer = ByteBuffer.New();              --框架定义序列化反序列字节流方法类。
    buffer:WriteShort(Login);                        --消息类型(写入Short类型)
    buffer:WriteByte(ProtocalType.PBC);      --协议类型(写入Byte类型)
    buffer:WriteBuffer(code);                         --消息体(LuaStringBuffer类里的Byte数组)

    NetManager:SendMessage(buffer);    --/发送消息


【C# 发送】

    //所属类必须继承View才能得到NetManager管理器,View继承自MonoBehaviour。
    void SendMessage()
    {
      ByteBuffer buffer = new  ByteBuffer();
      buffer.WriteShort(Protocal.Login);     
      buffer.WriteByte(0); // 0是 ProtocalType.BINARY ,回头要自己写一个枚举定义下
      buffer.WriteString("这是从C#发来的消息");
      buffer.WriteInt(200);
      NetManager.SendMessage(buffer); 
    }

可以先随便发送一个给服务器测试一下,我这边先不做Protobuf的发送,打算下一篇再研究,先实现能发送字符串。


3.接受服务器消息

注意:服务器发过来消息后,会有一个队列接受,所以只能由lua或者C#来处理,不能同时取一个消息来处理。如果实在要同时处理,那要自己去再添加一个队列,用2个队列,一个给Lua,一个给C#。

【Lua接收】

来到SocketCommand.cs类,就能看到只要接受到服务器的消息,就会执行给Network.lua的OnSocket函数。

switch (buffer.Key) {
            default: Util.CallMethod("Network", "OnSocket", buffer.Key, buffer.Value); break;
 }

Network.lua的OnSocket函数里广播分发服务器消息

function Network.OnSocket(key, data) --key(消息类型) data(消息体)
    Event.Brocast(tostring(key), data);
end

Event.AddListener(Login, this.OnLogin);实现消息订阅,参数1 消息类型 ,参数2 回调函数
Event.RemoveListener(Login);  --移除监听(会节省性能)


【C#接收】

先看,NetworkManager类:

        void Update() {
            if (sEvents.Count > 0) {
                while (sEvents.Count > 0) {
                    KeyValuePair<int, ByteBuffer> _event = sEvents.Dequeue();
                    //StartUpCommand实现关联  AppFacade.Instance.RegisterCommand(NotiConst.DISPATCH_MESSAGE, typeof(SocketCommand));
                    facade.SendMessageCommand(NotiConst.DISPATCH_MESSAGE, _event); //发消息给SocketCommand处理 
                }
            }
        }


再看,SocketCommand类:

    public override void Execute(IMessage message) {
        object data = message.Body;                               
        if (data == null) return;
        KeyValuePair<int, ByteBuffer> buffer = (KeyValuePair<int, ByteBuffer>)data;  //键值对

        //处理一个消息,就会从队列中移除该消息,所以不同把一个消息交给C#又给LUA,只能给其中一个。
        // C#的消息  在Protocal类中添加  Lua的消息  在Protocal.lua中添加  值切记不要搞混,比如C#消息值是1000的,Lua的就写1000以后
        switch (buffer.Key) {

            case Protocal.Login: //这里做演示,把Login消息给C#处理,本来是给Lua处理的。
               
               Debug.LogError("收到了Login消息,协议类型是:" + buffer.Value.ReadByte());
               Debug.LogError("收到了Login消息,消息体是:" + buffer.Value.ReadString());

                break;

            case Protocal.GameMessage: //新加的一个消息类型,值是1000 

               // Debug.LogError("收到了游戏消息,buffer.Value是:" + buffer.Value.ReadString());
                break;


            default: //如果不是游戏消息,交给Lua处理
                Util.CallMethod("Network", "OnSocket", buffer.Key, buffer.Value);
                break;
        }
	}

C#这边,应该写一个 静态委托类,在 SocketCommand类里按照返回不同的消息执行不同的委托,其他地方去订阅这个消息,具体看我的这篇博文    http://blog.csdn.net/u012322710/article/details/52911937

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是重阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值