0007-异步编程第二次重构

版权声明:本文为博主原创文章,未经博主允许不得转载。博客地址:http://blog.csdn.net/yy763496668 https://blog.csdn.net/yy763496668/article/details/89466682

在我们接受到消息后,其实应该有一个消息类出处理收发的消息,而减少ClientPeer的工作量。我们这次使用ProtoBuf封装一个消息。在这个消息中我们要包含消息来自哪一个模块,作用于那个函数,消息内容是什么。
因此我们定义了一个协议:
.proto文件

package ServerProtocol.Protocols;
message Message
{
	required int32 OpCode = 1;
	required int32 Subcode = 2;
	required bytes Value = 3;
}

生成cs文件,不再做展示,本文后将会有一个连接给出源码。
OpCode是对模块的划分,SubCode是对执行方法的划分,Value是真正的消息内容。Value我们没有使用对象,而是使用了一个字节数组。这样一个好处就是避免了继承关系。我们可以把传递的消息封装成一个对象。然后将对象序列化成一个字节数组。在我们得到接收到消息的时候再反序列化成一个对象即可。

我们创建一个cs文件EncodeMessageTool,在里面有四个静态函数
一个是封装消息包,消息长度+消息
一个是解析消息包
一个是序列化对象
一个是反序列化对象

using ProtoBuf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ServerProtocol
{
    public class EncodeMessageTool
    {


        /// <summary>
        /// 封装消息包
        /// </summary>
        public static byte[] EncodeMessage(byte[] data)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write(data.Length);
                    bw.Write(data);

                    byte[] byteArray = new byte[(int)ms.Length];
                    Buffer.BlockCopy(ms.GetBuffer(), 0, byteArray, 0, (int)ms.Length);
                    return byteArray;
                }
            }
        }
        /// <summary>
        /// 解析消息包
        /// </summary>
        public static byte[] DecodeMessage(List<byte> dataCache)
        {
            if (dataCache.Count < 4)
            {
                return null;
            }

            using (MemoryStream ms = new MemoryStream(dataCache.ToArray()))
            {
                using (BinaryReader br = new BinaryReader(ms))
                {
                    int length = br.ReadInt32();
                    int messageLength = (int)(ms.Length - ms.Position);
                    if (length > messageLength)
                    {
                        return null;
                    }
                    byte[] data = br.ReadBytes(length);
                    dataCache.Clear();
                    dataCache.AddRange(br.ReadBytes(messageLength));
                    return data;
                }
            }
        }



        /// <summary>
        /// 序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public static byte[] SerializeObject<T>(T t) where T : class
        {

            using (MemoryStream ms = new MemoryStream())
            {
                Serializer.Serialize<T>(ms, t);
                return ms.ToArray();
            }
        }
        /// <summary>
        /// 反序列化对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arr"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(byte[] arr) where T : class
        {

            using (MemoryStream ms = new MemoryStream(arr))
            {
                return Serializer.Deserialize<T>(ms);
            }

        }
    }
}

解决方案目录:
在这里插入图片描述
在上下两个工程中都是类库,上面的工程是写了游戏中所有相关的协议;下面这个写了有关游戏服务器套接字连接的逻辑。其实还应该有一个工程,负责游戏的逻辑。我们慢慢添加吧!今天的工程先写到这里。
工程在审核中,地址敬请期待。。

猜你喜欢

转载自blog.csdn.net/yy763496668/article/details/89466682
今日推荐