制定通信协议

                                                                                                           

                                               制定通信协议  

什么是制定通信协议?

    客户端在和服务器进行通信的时候,为了让双方都能辨别接收到的消息的内容,由发送方和接收方而制定的相关约定。

为什么制定通信协议?

在大型的网络游戏中,客户端和服务器发送的消息会很多很多,我们为了方便管理和区分这些消息,所以需要制定一些协议。比如说游戏登陆的时候,需要向服务器发送登陆的信息,我们把信息封装在登陆协议里面,直接把登陆协议发送给服务器。在做同步的时候,需要向服务器发送位置的信息,直接把同步协议发送给服务器,服务器可以通过协议的编号,来判断收到的协议是哪种协议,从而获取到相关的信息。

通信协议一般在哪里会用到?

    1.项目中各个模块之间传递消息

2. 客户端和服务端之间进行通信

如何去制定通信协议?

   1.为了方便区分每个协议,所以每个协议可以有一个唯一标识,我把它定位协议编号。

    所以我把它定义成属性放接口里面,每个协议都得去实现这个属性。

/// <summary>

/// 协议接口

/// </summary>

public interface  IProto {

 

/// <summary>

///协议编号

/// </summary>

 ushort ProtoID{get;}

}

  2.由于每个协议的内容肯定不一样,所以我们把内容放在具体协议类中,由于我用的是socket TCP通信,我的客户端和服务器制定的发送方法和接收方法参数是byte[] buffer数组,为了方便上层客户端调用,所以我们可以在具体协议类中加两个方法,第一方法是为了发送方便,第二个静态方法是为了接收方便。下面我通过一个具体协议来举例说明。

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

/// <summary>

/// 获取邮件详情

/// </summary>

public struct Mail_Get_DetailProto:IProto  {

 

    //此处编号为方便调用,特放在枚举里面

/// <summary>

/// 协议编号

/// </summary>

/// <value>The proto I.</value>

public ushort ProtoID{get{ return ProtoIDDef.Mail_Get_Proto;}}

 

/// <summary>

/// 是否发送成功

/// </summary>

public bool IsSuccess;

 

/// <summary>

/// 邮件名称

/// </summary>

public string Name;

 

/// <summary>

/// 错误编码

/// </summary>

public ushort ErrorCode;

 

/// <summary>

///转成流数组

/// </summary>

/// <returns>The array.</returns>

public byte[] ToArray()

{

using (MMO_MemoryStream ms = new MMO_MemoryStream ()) {

ms.WriteUShort (ProtoID);

ms.WriteBool (IsSuccess);

if (IsSuccess) {

ms.WriteUTF8String (Name);

} else {

ms.WriteUShort (ErrorCode);

}

return ms.ToArray ();

}

}

 

/// <summary>

///获取协议

/// </summary>

/// <returns>The proto.</returns>

/// <param name="buffer">Buffer.</param>

public static   Mail_Get_DetailProto GetProto(byte[] buffer)

{

Mail_Get_DetailProto proto = new Mail_Get_DetailProto ();

using (MMO_MemoryStream ms = new MMO_MemoryStream (buffer)) {

proto.IsSuccess = ms.ReadBool ();

if (proto.IsSuccess) {

proto.Name = ms.ReadUTF8String ();

} else {

proto.ErrorCode = ms.ReadUShort ();

}

}

return proto;

}

}

3. 基于Http的通信协议制定

做弱联网游戏或者模块通信的时候呢,一般呢是采用Http的,比如说做Web服务器项目和客户端Unity项目通信的时候,由于底层已经封装好,参数是json格式的字符串,所以我们的协议还得序列化成json格式,接收到的时候,把json对象反序列化成我们的数据对象。

 

通过项目中实际代码说明一下吧,下面是客户端的注册逻辑过程。

 /// <summary>

    /// 注册窗口

    /// </summary>

    private void OnBtnRegisterClick()

    {

        //注册逻辑TODO

        nickName = m_InputeNickName.text.Trim();

        string pwd = m_InputNickPassword.text.Trim();

        string pwd2 = m_InputReNickPassword.text.Trim();

        if(string.IsNullOrEmpty(nickName))

        {

            m_TextTip.text = "提示:请输入账号!";

            return;

        }

 

        if (string.IsNullOrEmpty(pwd))

        {

            m_TextTip.text = "提示:请输入密码!";

            return;

        }

        if(string.IsNullOrEmpty(pwd2))

        {

            m_TextTip.text = "提示:请输入确认密码!";

            return;

        }

        if(pwd!=pwd2)

        {

            m_TextTip.text = "提示:两次输入密码不一致!";

            return;

        }

        if(nickName.Length<8)

        {

            m_TextTip.text = "提示:昵称最少为8个有效字符";

            return;

        }

        else if(nickName.Length>16)

        {

            m_TextTip.text = "提示:昵称最多为16个有效字符";

            return;

        }

        if (pwd.Length < 8)

        {

            m_TextTip.text = "提示:密码最少为8个有效字符";

            return;

        }

        else if (pwd.Length > 16)

        {

            m_TextTip.text = "提示:密码最多为16个有效字符";

            return;

        }

        if (!string.IsNullOrEmpty(nickName)&&!string.IsNullOrEmpty(pwd))

        {

//把数据发送到服务器

JsonData jsonData=new JsonData();

jsonData ["Type"] = 1;

jsonData ["UserName"] = nickName;

jsonData ["Pwd"] = pwd;

             //把消息提交到web服务器

NetWorkHTTP.Instance.SendData (GlobalInit.WebAccountUrl + "api/Account", PostCallBack, true, jsonData.ToJson ());

}

       else

        {

            m_TextTip.text = "提示:请输入账号或密码!";

            return;

        }

    }

   //提交消息回调方法

private void PostCallBack(NetWorkHTTP.CallBackArgs obj)

{

if (obj.isError)

{

Debug.Log(obj.Error);

}

else

{

 

RetValue ret = JsonMapper.ToObject<RetValue>(obj.Json);

 

            if (ret.RetData == "注册成功")

            {

                JsonData jsonData = new JsonData();

                jsonData["Type"] = 2;

                jsonData["UserName"] = nickName;

                jsonData["LoginTime"] = DateTime.Now.ToString();

                jsonData["IsOnLine"] = 1;

                NetWorkHTTP.Instance.SendData(GlobalInit.WebAccountUrl + "api/Account", PostCallBack, true, jsonData.ToJson());

                GameSceneManager.Instance.LoadGameScene(SceneType.Scene_MainCity);

            }

            else

            {

                Debug.Log(ret.RetData);

                m_TextTip.text = ret.RetData;

            }

 

        }

}

 

下面是Web服务器对接收到的消息进行处理

 

        // POST: api/Account

        public RetValue Post([FromBody]string jsonStr)

        {

            RetValue ret = new RetValue();

            try

            {

                JsonData jsonData = JsonMapper.ToObject<JsonData>(jsonStr);

 

                int type = int.Parse(jsonData["Type"].ToString());

 

                if (type == 0)

                {

                    //登陆协议

                    string userName = jsonData["UserName"].ToString();

                    string pwd = jsonData["Pwd"].ToString();

                    //登陆 去数据库里面进行查找,比较用户名和密码是否相等

 

                    AccountData account = DBManager.GetUserByUsername(userName);

                    //如果数据表为空,则此用户名不存在

                    if (account == null)

                    {

                        //发送 此用户不存在

                        ret.RetData = "此账号不存在";

 

                    }

                    //否则比较密码是否一致

                    else

                    {

                        //先验证密码是否正确,如果正确,再去验证是否在线

                        if (account.Pwd == pwd && account.IsOnLine == 0)

                        {

                            //可以登陆

                            ret.HasError = false;

                            ret.RetData = "账号密码正确";

 

                        }

                        else if (account.Pwd == pwd && account.IsOnLine == 1)

                        {

                            //此用户已在线

                            ret.HasError = false;

                            ret.RetData = "此用户已经在线";

 

                        }

                        else

                        {

                            //发送密码不正确

                            ret.HasError = false;

                            ret.RetData = "账号密码不匹配,请重新登录";

                        }

                    }

                }

                else if (type == 1)

                {

                    //注册协议

                    string userName = jsonData["UserName"].ToString();

                    string pwd = jsonData["Pwd"].ToString();

                    //先去数据库里面查询是否有相同的用户名,如果有的话,返回此账号已经存在

                    AccountData accountTemp = DBManager.GetUserByUsername(userName);

                    if (accountTemp != null)

                    {

                            ret.HasError = false;

                            ret.RetData = "此账号已经存在";

     

                    }

                    else 

                    {

                        AccountData account = new AccountData();

                        account.UserName = userName;

                        account.Pwd = pwd;

                        account.CreateTime = DateTime.Now;

                        DBManager.SaveUser(account);

                        ret.HasError = false;

                        ret.RetData = "注册成功";

                    }

                }

                else if (type == 2)

                {

                    //登陆信息协议

                    string userName = jsonData["UserName"].ToString();

                    DateTime loginTime = Convert.ToDateTime(jsonData["LoginTime"].ToString());

                    int isOnLine =Convert.ToInt32( jsonData["IsOnLine"].ToString());

                    AccountData account = DBManager.GetUserByUsername(userName);

                    account.UserName = userName;

                    account.LoginTime = loginTime;

                    account.IsOnLine = isOnLine;

                    DBManager.UpdateUserByName("t_account1", new string[] { "LoginTime", "IsOnLine" }, new string[] { loginTime.ToString("yyyyMMddHHmmss"), isOnLine.ToString() }, "UserName", userName);

                }

            }

            catch (Exception e)

            {

                ret.HasError = true;

                ret.Error = e.Message;

              

            }

            return ret;

 

        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值