【游戏技术群】959392658  【游戏出海群】12067810
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2422

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

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

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

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

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

18

主题

197

帖子

3797

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
17
蛮牛币
5161
威望
0
注册时间
2013-7-4
在线时间
1546 小时
最后登录
2019-2-23

专栏作家社区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 很给力!

查看全部评分


回复

使用道具 举报

7日久生情
1745/5000
排名
1258
昨日变化
1

0

主题

507

帖子

1745

积分

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

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

回复 支持 反对

使用道具 举报

5熟悉之中
677/1000
排名
4291
昨日变化
6

1

主题

211

帖子

677

积分

Rank: 5Rank: 5

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

回复

使用道具 举报

5熟悉之中
891/1000
排名
2572
昨日变化
29

1

主题

61

帖子

891

积分

Rank: 5Rank: 5

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

回复

使用道具 举报

7日久生情
3555/5000
排名
1555
昨日变化
8

0

主题

2131

帖子

3555

积分

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

UID
219676
好友
1
蛮牛币
2826
威望
0
注册时间
2017-7-12
在线时间
604 小时
最后登录
2019-2-22

活力之星

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

回复

使用道具 举报

6蛮牛粉丝
1029/1500
排名
3688
昨日变化
36

0

主题

303

帖子

1029

积分

Rank: 6Rank: 6Rank: 6

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

回复 支持 反对

使用道具 举报

排名
438
昨日变化
1

18

主题

197

帖子

3797

积分

Rank: 9Rank: 9Rank: 9

UID
686
好友
17
蛮牛币
5161
威望
0
注册时间
2013-7-4
在线时间
1546 小时
最后登录
2019-2-23

专栏作家社区QQ达人

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

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

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1029/1500
排名
3688
昨日变化
36

0

主题

303

帖子

1029

积分

Rank: 6Rank: 6Rank: 6

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

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1076/1500
排名
2462
昨日变化
4

1

主题

153

帖子

1076

积分

Rank: 6Rank: 6Rank: 6

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

回复

使用道具 举报

4四处流浪
347/500
排名
11155
昨日变化
7

0

主题

209

帖子

347

积分

Rank: 4

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

回复 支持 反对

使用道具 举报

5熟悉之中
883/1000
排名
3444
昨日变化
4

5

主题

178

帖子

883

积分

Rank: 5Rank: 5

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

回复

使用道具 举报

5熟悉之中
920/1000
排名
2422
昨日变化
5

6

主题

42

帖子

920

积分

Rank: 5Rank: 5

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

回复 支持 反对

使用道具 举报

7日久生情
1699/5000
排名
3064
昨日变化
7

5

主题

889

帖子

1699

积分

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

UID
246489
好友
1
蛮牛币
2641
威望
0
注册时间
2017-9-28
在线时间
327 小时
最后登录
2019-2-15

活力之星

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

回复

使用道具 举报

7日久生情
1690/5000
排名
1646
昨日变化
4

0

主题

406

帖子

1690

积分

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

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

回复

使用道具 举报

4四处流浪
499/500
排名
4054
昨日变化
30

1

主题

14

帖子

499

积分

Rank: 4

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

回复

使用道具 举报

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

本版积分规则

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