游戏蛮牛学习群(纯技术交流,不闲聊):159852603
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2309

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1820|回复: 28

[薛飞] Unity极简网络游戏之消息协议和消息处理

[复制链接]  [移动端链接]
排名
600
昨日变化
1

17

主题

188

帖子

3243

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
12
蛮牛币
4287
威望
0
注册时间
2013-7-4
在线时间
1280 小时
最后登录
2018-9-19

专栏作家社区QQ达人

QQ
发表于 2018-6-4 20:09:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
项目托管在码云上https://gitee.com/awnuxcvbn/Ganghood,如有未涉及到的代码,请下载或直接浏览
消息协议使用Protobuf,这里简单说一下Protobuf C#版使用,写类似如下的消息协议,然后生成C#代码
[C#] 纯文本查看 复制代码
package Message;

message CToSChat
{
	required int32 fromuid = 1;
	required string fromuname = 2;
	required int32 touid =3;
	required string touname =4;
	required string content = 5;
}

message SToCChat
{
	required int32 fromuid = 1;
	required string fromuname = 2;
	required int32 touid =3;
	required string touname =4;
	required string content = 5;
}




生成proto的C#代码的批处理
[C#] 纯文本查看 复制代码
@echo off  
rem 查找文件  
for /f "delims=" %%i in ('dir /b ".\*.proto"') do echo %%i  
rem 转cpp  for /f "delims=" %%i in ('dir /b/a "*.proto"') do protoc -I=. --cpp_out=. %%i  
for /f "delims=" %%i in ('dir /b/a "*.proto"') do protogen -i:%%i -o:%%~ni.cs  
pause




生成proto的C#代码

生成proto的C#代码




消息处理过程:
1、Socket接受数据缓存到队列
[C#] 纯文本查看 复制代码
private List<byte> receiveCache = new List<byte>();


2、反序列化byte数组为protobuf消息体
[C#] 纯文本查看 复制代码
 Type protoType = ProtoDic.GetProtoTypeByProtoId(protoId);
            object tos = ProtoBuf.Serializer.Deserialize(protoType, new MemoryStream(data));

3、分发消息体给监听者
[C#] 纯文本查看 复制代码
object[] args = new object[1];
            args[0] = tos;

            MsgMgr.Instance.SendMsg(protoType.ToString(), args);




接下来主要看一下第2步中数据包处理的代码,把发送的消息按照 消息id+消息长度+消息内容 的格式进行拼接,用于处理粘包问题
这里仅粘贴主要代码NetCode
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.IO;

/// <summary>
/// 编码和解码
/// </summary>
public class NetCode
{
    /// <summary>
    /// 将数据编码 消息id+消息长度+消息内容
    /// </summary>
    /// <param name="protoId"></param>
    /// <param name="proto"></param>
    /// <returns></returns>
    public static byte[] Encode(object proto)
    {
        Type type = proto.GetType();
        int protoId = ProtoDic.GetProtoIdByProtoType(type);
        MemoryStream ms = new MemoryStream();
        ProtoBuf.Serializer.Serialize(ms, proto);
        byte[] data = ms.ToArray();
        ms.Dispose();
        ms = new MemoryStream();
        //整形占四个字节,所以声明一个+4+4+消息长度的数组
        byte[] result = new byte[data.Length + 8];
        //使用流将编码写二进制 
        BinaryWriter br = new BinaryWriter(ms);

        br.Write(protoId);
        br.Write(data.Length);
        br.Write(data);
        //将流中的内容复制到数组中
        Buffer.BlockCopy(ms.ToArray(), 0, result, 0, (int)ms.Length);
        br.Close();
        ms.Close();
        //Debug.LogWarning("编码消息id " + protoId + " 长度 " + result.Length + " 内容 " + GetDesc(result));
        return result;
    }

    /// <summary>
    /// 将数据解码
    /// </summary>
    /// <param name="cache">消息队列</param>
    public static byte[] Decode(ref int protoId, ref List<byte> cache)
    {
        //首先要获取消息长度,整形4个字节,如果字节数不足4个字节
        if (cache.Count < 4)
        {
            return null;
        }
        //读取数据
        MemoryStream ms = new MemoryStream(cache.ToArray());
        BinaryReader br = new BinaryReader(ms);
        protoId = br.ReadInt32();
        //消息长度
        int len = br.ReadInt32();
        //根据长度,判断内容是否传递完毕
        if (len > ms.Length - ms.Position)
        {
            return null;
        }
        //获取数据
        byte[] result = br.ReadBytes(len);
        //Debug.LogWarning("解码消息id " + protoId + " 长度 " + len + " 内容 " + GetDesc(result));
        //清空消息池
        cache.Clear();
        //将剩余没处理的消息存入消息池
        cache.AddRange(br.ReadBytes((int)ms.Length - (int)ms.Position));

        return result;
    }

    public static string GetDesc(byte[] bytes)
    {
        string str = "";
        if (bytes == null)
            return str;
        for (int i = 0; i < bytes.Length; i++)
        {
            int b = (int)bytes[i];
            str += b.ToString() + " ";
        }
        return str;
    }
}




然后是第3步,消息的分发,贴一下主要代码
[C#] 纯文本查看 复制代码
using System.Collections.Generic;
using UnityEngine;

//委托类型
public delegate void MsgDelegate(object[] args);

/// <summary>
/// 消息分发
/// </summary>
public class MsgMgr : MonoBehaviour
{
    public static MsgMgr Instance;
      
    //消息列表
    public Dictionary< string, MsgDelegate> msgDic;
     

    public MsgMgr()
    {
        Instance = this;
        msgDic = new Dictionary<string, MsgDelegate>(); 
    } 

    /// <summary>
    /// 添加事件监听 
    /// </summary>
    /// <param name="name"></param>
    /// <param name="cb"></param>
    public void AddListener(string name, MsgDelegate cb)
    { 
        if (!msgDic.ContainsKey(name))
        {
            msgDic.Add(name, cb); 
        }
        else
        {
            msgDic[name] += cb;
        }
    }

    /// <summary>
    /// 添加事件监听 
    /// </summary>
    /// <param name="name"></param>
    /// <param name="cb"></param>
    public void RemoveListener(string name, MsgDelegate cb)
    {
        if (msgDic.ContainsKey(name))
        {
            msgDic[name] -= cb;
        }
        else
        {
            msgDic.Remove(name);
        }
    }

    /// <summary>
    /// 清除所有的监听者
    /// </summary>
    public  void ClearAllListeners()
    {
        msgDic.Clear();
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="name"></param>
    /// <param name="args"></param>
    public void SendMsg(string name, params object[] args)
    {
        MsgDelegate cb;
        if (msgDic.TryGetValue(name, out cb))
        {
            if (cb != null)
            {
                cb(args);
            }
        }
    }
     
}


评分

参与人数 1鲜花 +5 收起 理由
nianhua2008 + 5 很给力!

查看全部评分


回复

使用道具 举报

6蛮牛粉丝
1304/1500
排名
1776
昨日变化
6

0

主题

377

帖子

1304

积分

Rank: 6Rank: 6Rank: 6

UID
87577
好友
0
蛮牛币
4267
威望
0
注册时间
2015-3-31
在线时间
225 小时
最后登录
2018-9-19
发表于 2018-6-5 08:36:07 | 显示全部楼层
too good too strong!

回复 支持 反对

使用道具 举报

4四处流浪
374/500
排名
6696
昨日变化
52

0

主题

114

帖子

374

积分

Rank: 4

UID
245227
好友
0
蛮牛币
433
威望
0
注册时间
2017-9-21
在线时间
72 小时
最后登录
2018-9-19
发表于 2018-6-5 09:04:10 | 显示全部楼层
不错

回复

使用道具 举报

5熟悉之中
618/1000
排名
3804
昨日变化
17

1

主题

54

帖子

618

积分

Rank: 5Rank: 5

UID
227966
好友
0
蛮牛币
623
威望
0
注册时间
2017-6-21
在线时间
199 小时
最后登录
2018-9-19
发表于 2018-6-5 09:25:57 | 显示全部楼层
学习学习

回复

使用道具 举报

7日久生情
3230/5000
排名
2076
昨日变化
1

0

主题

2115

帖子

3230

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
219676
好友
1
蛮牛币
2414
威望
0
注册时间
2017-7-12
在线时间
491 小时
最后登录
2018-9-19

活力之星

发表于 2018-6-5 10:26:24 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
748/1000
排名
5319
昨日变化
3

0

主题

279

帖子

748

积分

Rank: 5Rank: 5

UID
180321
好友
4
蛮牛币
583
威望
0
注册时间
2016-11-21
在线时间
217 小时
最后登录
2018-9-19
发表于 2018-6-5 10:34:47 | 显示全部楼层
看了你们的网站,网站是只有服务端的,
[发帖际遇]: liuzhaoyun 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
600
昨日变化
1

17

主题

188

帖子

3243

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
12
蛮牛币
4287
威望
0
注册时间
2013-7-4
在线时间
1280 小时
最后登录
2018-9-19

专栏作家社区QQ达人

QQ
 楼主| 发表于 2018-6-5 10:39:24 | 显示全部楼层
liuzhaoyun 发表于 2018-6-5 10:34
看了你们的网站,网站是只有服务端的,

客户端也有啊 TIM截图20180605103836.png

回复 支持 反对

使用道具 举报

5熟悉之中
748/1000
排名
5319
昨日变化
3

0

主题

279

帖子

748

积分

Rank: 5Rank: 5

UID
180321
好友
4
蛮牛币
583
威望
0
注册时间
2016-11-21
在线时间
217 小时
最后登录
2018-9-19
发表于 2018-6-5 10:56:40 | 显示全部楼层
不好意思,没看清楚,好东西
[发帖际遇]: liuzhaoyun 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
764/1000
排名
3459
昨日变化
12

1

主题

129

帖子

764

积分

Rank: 5Rank: 5

UID
236305
好友
1
蛮牛币
1067
威望
0
注册时间
2017-8-7
在线时间
232 小时
最后登录
2018-9-19
发表于 2018-6-5 10:57:10 | 显示全部楼层
前来学习一下

回复

使用道具 举报

4四处流浪
321/500
排名
11205
昨日变化
1

0

主题

194

帖子

321

积分

Rank: 4

UID
251531
好友
0
蛮牛币
442
威望
0
注册时间
2017-10-30
在线时间
47 小时
最后登录
2018-8-16
发表于 2018-6-5 11:10:10 | 显示全部楼层
66666666666666666

回复 支持 反对

使用道具 举报

5熟悉之中
816/1000
排名
3578
昨日变化
1

5

主题

176

帖子

816

积分

Rank: 5Rank: 5

UID
207446
好友
0
蛮牛币
2013
威望
0
注册时间
2017-2-20
在线时间
251 小时
最后登录
2018-9-13
发表于 2018-6-5 15:32:11 | 显示全部楼层

回复

使用道具 举报

5熟悉之中
781/1000
排名
2812
昨日变化
15

6

主题

41

帖子

781

积分

Rank: 5Rank: 5

UID
208647
好友
4
蛮牛币
1183
威望
0
注册时间
2017-2-26
在线时间
252 小时
最后登录
2018-9-18
发表于 2018-6-5 16:25:22 | 显示全部楼层
谢谢分享,赶紧学习一下,嘻嘻

回复 支持 反对

使用道具 举报

7日久生情
1629/5000
排名
3048
昨日变化
11

3

主题

867

帖子

1629

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
246489
好友
1
蛮牛币
2703
威望
0
注册时间
2017-9-28
在线时间
311 小时
最后登录
2018-9-17

活力之星

发表于 2018-6-6 09:04:25 | 显示全部楼层
谢谢分享
[发帖际遇]: ss_luck 乐于助人,奖励 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

6蛮牛粉丝
1383/1500
排名
2098
昨日变化
6

0

主题

364

帖子

1383

积分

Rank: 6Rank: 6Rank: 6

UID
136635
好友
0
蛮牛币
1400
威望
0
注册时间
2016-2-15
在线时间
399 小时
最后登录
2018-9-19
发表于 2018-6-6 09:18:52 | 显示全部楼层
很好,谢谢
[发帖际遇]: hed_tan 被钱袋砸中进医院,看病花了 2 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

3偶尔光临
254/300
排名
6872
昨日变化
43

1

主题

11

帖子

254

积分

Rank: 3Rank: 3Rank: 3

UID
279082
好友
0
蛮牛币
519
威望
0
注册时间
2018-4-27
在线时间
62 小时
最后登录
2018-9-19
发表于 2018-6-6 09:22:30 | 显示全部楼层
学习学习啦

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表