Moba项目开发(一)打造网络通信系统-任务6:06.编写构建ACK报文的接口和总结前面做了啥

1)构建请求报文

public BufferEntity(IPEndPoint endPoint, int session, int sn, int moduleID, int messageType, int messageID, byte[] proto)

2)构建收到的报文实体

public BufferEntity(IPEndPoint endPoint,byte[] buffer)

3)将报文反序列化成实体里面的成员

private void Decode()

4)创建一个ACK报文的实体接受反序列化好的数据,这里的package是收到报文实体后,已经反序列化好的

public BufferEntity(BufferEntity package)

5)代码

using System.Net;                      //用了public IPEndPoint endPoint;要加
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//先建立命名空间
namespace Game.Net
{
    public class BufferEntity
    {
        //全局变量
        public int recurCount = 0;     //记录重发次数,工程内部用到(记录网络拥塞),并非业务数据
        public IPEndPoint endPoint;    //发送的目标终端,里面记录了IP和端口

        public int protoSize;          //协议大小,用于确认报文的完整性
        public int session;            //会话ID,用于识别客户端的唯一性
        public int sn;                 //序号,用于保证报文的顺序
        public int moduleID;           //模块ID,把报文传递给对应模块/程序
        public long time;              //发送时间,用于判断是否超时
        public int messageType;        //协议类型,区分协议的细节(比如101要登录,102要注册)
        public int messageID;          //协议ID,用于区分业务
        public byte[] proto;           //业务报文,记录业务数据

        //需要一个字段全部组装成一个byte数组,作为发送的字段
        public byte[] buffer;          //最终要发送的数据 或者是  收到的数据

        //创建一个请求报文的接口,用构造函数
        //第一个参数是我们要发送的终端,第二个参数是会话ID,第三个参数是序号,以此类推
        //构建请求报文
        public BufferEntity(IPEndPoint endPoint, int session, int sn, int moduleID, int messageType, int messageID, byte[] proto)
        {
            protoSize = proto.Length;  //业务数据大小
            this.endPoint = endPoint;
            this.session = session;
            this.sn = sn;
            this.moduleID = moduleID;
            this.messageType = messageType;
            this.proto = proto;
        }

        //编码的接口,把这些成员组装成要发送的数据,也就是 byte[]
        //编码有两种格式,一种是ACK确认报文,一种是业务报文
        //ACK不需要带上包体,只需要带上序号
        //以后发送数据就用这个接口
        public byte[] Encoder(bool isAck)
        {
            //上面的数据加起来有32个字节
            byte[] data = new byte[32 + protoSize];
            //开始往data写入数据,写入之前要把int、long类型转化为byte类型的数据
            //BitConverter将各种类型转化为byte类型
            byte[] _length = BitConverter.GetBytes(protoSize);
            byte[] _session = BitConverter.GetBytes(session);
            byte[] _sn = BitConverter.GetBytes(sn);
            byte[] _moduleid = BitConverter.GetBytes(moduleID);
            byte[] _time = BitConverter.GetBytes(time);
            byte[] _messageID = BitConverter.GetBytes(messageID);
            byte[] _messageType = BitConverter.GetBytes(messageType);

            //要将字节数组,写入到data
            //第一个参数是长度,第二个蚕食表示从date的首地址开始写入,
            //第三个参数是写入的数据,第四个参数表示在结构体中的数据,第五个参数表示data的大小
            Array.Copy(_length, 0, data, 0, 4);
            Array.Copy(_session, 0, data, 4, 4);
            Array.Copy(_sn, 0, data, 8, 4);
            Array.Copy(_moduleid, 0, data, 12, 4);
            Array.Copy(_time, 0, data, 16, 8);
            Array.Copy(_messageType, 0, data, 24, 4);
            Array.Copy(_messageID, 0, data, 28, 4);

            //若是ACK包
            if (isAck)
            {
                //如果是ACK,不做任何处理
            }
            else
            {
                //如果这个包是业务数据,追加进来
                Array.Copy(proto, 0, data, 32, proto.Length);
            }
            //对全局变量buffer赋值
            buffer = data;
            return data;
        }

        //需要一个构造函数,接受报文数据
        //构建接收到的报文实体
        public BufferEntity(IPEndPoint endPoint,byte[] buffer)
        {
            this.endPoint = endPoint;    //终端IP
            this.buffer = buffer;        //收到的数据
            Decode();
        }

        //当我们收到客户端的报文,或服务器收到客户端的报文,要怎么处理收到的报文
        //将报文反序列化成实体里面的成员
        private void Decode()
        {
            //将字节数组转化成int或long
            //Toint32,转化成int对象
            //Toint64,转换成long对象
            protoSize = BitConverter.ToInt32(buffer,0);    //从0的位置,取四个字节转成int
            session = BitConverter.ToInt32(buffer, 4);     //从4的位置,取四个字节转换成int
            sn = BitConverter.ToInt32(buffer, 8);          //从8的位置,取四个字节抓换成int
            moduleID = BitConverter.ToInt64(buffer, 12);   
            time = BitConverter.ToInt32(buffer, 16);       //从16的位置,取八个字节转换成int
            messageType = BitConverter.ToInt32(buffer, 24);
            messageID = BitConverter.ToInt32(buffer, 28);

            //messageType为0表示ACK报文
            if (0 == messageType)
            {

            }
            //否则为业务数据
            else
            {
                //new一个空间来存业务数据,空间大小为protoSize
                proto = new byte[protoSize];
                //把buffer剩下的数据复制到proto,也就是将buffer32位以后的数据复制到proto里面,复制大小为protoSize的大小
                Array.Copy(buffer, 32, proto, 0, protoSize);
            }
        }

        //创建一个ACK报文的实体,这里的package是收到报文实体后,已经反序列化好的
        public BufferEntity(BufferEntity package)
        {
            protoSize = 0;                      //ACK无业务数据
            this.endPoint = package.endPoint;
            this.session = package.session;
            this.sn = package.sn;
            this.moduleID = package.moduleID;
            this.time = 0;                      //发送时间都是0,因为都是发送的时候外部进行修改的
            this.messageType = 0;               //0表示ACK报文
            this.messageID = package.messageID;
            //
            buffer = Encoder(true);


        }




    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值