【极】P4网络消息处理_通讯与协议(客户端通信)


前言

完成项目的注册登录系统,了解与服务器进行交互以及数据校验,为了方面这边就用注释的方式来阐述。
在这里插入图片描述


一、UI准备

注册登录的UI按个人喜好而定,基本上的输入就那几块,我这边就简单演示,主要是代码注释的形式,更加的人性化

登录
在这里插入图片描述
注册
在这里插入图片描述

二、客户端逻辑脚本编写

为了减少耦合性,这边login为一个脚本,register为一个脚本,并挂载到响应的UI组件上

UserService 处理UI层传递参数,进行逻辑处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using Network;
using UnityEngine;

using SkillBridge.Message;

namespace Services
{
    
    
    class UserService : Singleton<UserService>, IDisposable
    {
    
    

   
        public UnityEngine.Events.UnityAction<Result, string> OnRegister; //创建注册事件
        public UnityEngine.Events.UnityAction<Result, string> OnLogin; //创建登录事件
        NetMessage pendingMessage = null; //存储因链接断开而未能发送的信息
        bool connected = false; //判断链接是否连通

        public UserService()  //构造函数
        {
    
    
            NetClient.Instance.OnConnect += OnGameServerConnect;  //添加链接事件
            NetClient.Instance.OnDisconnect += OnGameServerDisconnect; //添加断开事件
            MessageDistributer.Instance.Subscribe<UserRegisterResponse>(this.OnUserRegister); //注册消息分发,执行注册方法
            MessageDistributer.Instance.Subscribe<UserLoginResponse>(this.OnUserLogin); // //登录消息分发,执行注册方法
            
        }

        public void Dispose() 
        {
    
    
            MessageDistributer.Instance.Unsubscribe<UserRegisterResponse>(this.OnUserRegister);
            MessageDistributer.Instance.Unsubscribe<UserLoginResponse>(this.OnUserLogin);

            NetClient.Instance.OnConnect -= OnGameServerConnect;
            NetClient.Instance.OnDisconnect -= OnGameServerDisconnect;
        }

        public void Init()
        {
    
    

        }

        public void ConnectToServer()
        {
    
    
            Debug.Log("ConnectToServer() Start ");
            //NetClient.Instance.CryptKey = this.SessionId;
            NetClient.Instance.Init("127.0.0.1", 8000);
            NetClient.Instance.Connect();
        }


        void OnGameServerConnect(int result, string reason) //链接方法
        {
    
    
            Log.InfoFormat("LoadingMesager::OnGameServerConnect :{0} reason:{1}", result, reason);
            if (NetClient.Instance.Connected) //判断链接是否
            {
    
    
                this.connected = true; //至为True;
                if(this.pendingMessage!=null) //判断上次链接是否剩下信息没有发送
                {
    
    
                    NetClient.Instance.SendMessage(this.pendingMessage); //把没有发送的重新发送
                    this.pendingMessage = null;//清空
                }
            }
            else
            {
    
    
                if (!this.DisconnectNotify(result, reason))
                {
    
    
                    MessageBox.Show(string.Format("网络错误,无法连接到服务器!\n RESULT:{0} ERROR:{1}", result, reason), "错误", MessageBoxType.Error);
                }
            }
        }

        public void OnGameServerDisconnect(int result, string reason) //断开方法
        {
    
    
            this.DisconnectNotify(result, reason);
            return;
        }

        bool DisconnectNotify(int result,string reason)
        {
    
    
            if (this.pendingMessage != null)
            {
    
    
               
               
                    if (this.OnRegister != null)
                    {
    
    
                        this.OnRegister(Result.Failed, string.Format("服务器断开!\n RESULT:{0} ERROR:{1}", result, reason));
                    }
                
               
                return true;
            }
            return false;
        }

       

        public void SendRegister(string user, string psw) //注册信息发送
        {
    
    
            Debug.LogFormat("UserRegisterRequest::user :{0} psw:{1}", user, psw);
            NetMessage message = new NetMessage(); //创建网络消息用来跟服务端通信
            message.Request = new NetMessageRequest();//实例化消息请求
            message.Request.userRegister = new UserRegisterRequest(); //实例化注册请求
            message.Request.userRegister.User = user; //给注册请求参数赋值
            message.Request.userRegister.Passward = psw;

            if (this.connected && NetClient.Instance.Connected) //判断链接是否链接上
            {
    
    															//链接上就发送之前没有发送的消息
                this.pendingMessage = null;
                NetClient.Instance.SendMessage(message);
            }
            else       //没有链接上就把未能发送的消息存储,并执行重连
            {
    
    
                this.pendingMessage = message;
                this.ConnectToServer();
            }
        }

        void OnUserRegister(object sender, UserRegisterResponse response) //注册响应事件
        {
    
    
            Debug.LogFormat("OnUserRegister:{0} [{1}]", response.Result, response.Errormsg);

            if (this.OnRegister != null)
            {
    
    
                this.OnRegister(response.Result, response.Errormsg);

            }
        }

        void OnUserLogin(object sender,UserLoginResponse response)//登录响应事件
        {
    
    
            Debug.LogFormat("OnUserLogin:{0} [{1}]", response.Result, response.Errormsg);

            if (this.OnLogin != null)
            {
    
    
                this.OnLogin(response.Result, response.Errormsg);

            }
        }

        public void SendLogin(string user,string psw)    //发送登录信息,和发送注册差不多
        {
    
    
            Debug.LogFormat("OnUserLogin::user:{0} psw:{1}", user, psw);
            NetMessage message = new NetMessage();
            message.Request = new NetMessageRequest();
            message.Request.userLogin = new UserLoginRequest();
            message.Request.userLogin.User = user;
            message.Request.userLogin.Passward = psw;
            if (this.connected && NetClient.Instance.Connected)
            {
    
    
                this.pendingMessage = null;
                NetClient.Instance.SendMessage(message);
            }
            else
            {
    
    
                this.pendingMessage = message;
                this.ConnectToServer();
            }

        }

      
}

1.登录脚本

UILogin.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Services;
using SkillBridge.Message;
using TMPro;

public class UILogin : MonoBehaviour {
    
    

    public TMP_InputField username; //这边使用TMP的原因是因为比原生的GUI性能强
    public TMP_InputField password;

    // Use this for initialization
    void Start () {
    
    
      UserService.Instance.OnLogin = OnLogin; //开始先执行一次登录消息的创建,保证链接是通畅的
    }


    // Update is called once per frame
    void Update () {
    
    
		
	}

    public void OnClickLogin() //登录按钮按下时
    {
    
    
        if (string.IsNullOrEmpty(this.username.text)) //判断当前输入框是否为空
        {
    
    
            MessageBox.Show("请输入账号");
            return;
        }
        if (string.IsNullOrEmpty(this.password.text))
        {
    
    
            MessageBox.Show("请输入密码");
            return;
        }
        // Enter Game
      UserService.Instance.SendLogin(this.username.text,this.password.text); //传递参数,让Service处理请求

    }

    void OnLogin(Result result, string message)
    {
    
    
    //接收从服务器传来的Result类型和消息
        if (result == Result.Success)
        {
    
    
            //登录成功,进入角色选择
           MessageBox.Show("登录成功,准备角色选择" + message,"提示", MessageBoxType.Information);
            SceneManager.Instance.LoadScene("CharSelect");

        }
        else
            MessageBox.Show(message, "错误", MessageBoxType.Error);
    }
}

2.注册脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Services;
using SkillBridge.Message;
using TMPro;

public class UIRegister : MonoBehaviour {
    
    


    public TMP_InputField username;
    public TMP_InputField password;
    public TMP_InputField passwordConfirm;
    public Button buttonRegister;

    public GameObject uiLogin;
    // Use this for initialization
    void Start () {
    
    
        UserService.Instance.OnRegister = OnRegister; //和Login一致 先链接
        
    }

    // Update is called once per frame
    void Update () {
    
    
        Debug.Log(username.text);
        Debug.Log(username);
    }

    public void OnClickRegister()
    {
    
    
        if (string.IsNullOrEmpty(this.username.text)) //数据校验进行判空
        {
    
    
            MessageBox.Show("请输入账号");
            return;
        }
        if (string.IsNullOrEmpty(this.password.text))
        {
    
    
            MessageBox.Show("请输入密码");
            return;
        }
        if (string.IsNullOrEmpty(this.passwordConfirm.text))
        {
    
    
            MessageBox.Show("请输入确认密码");
            return;
        }
        if (this.password.text != this.passwordConfirm.text)
        {
    
    
            MessageBox.Show("两次输入的密码不一致");
            return;
        }

        UserService.Instance.SendRegister(this.username.text,this.password.text); //发送注册消息
    }


    void OnRegister(Result result, string message)
    {
    
    
        if (result == Result.Success) //处理服务器返回的信息
        {
    
    
            //登录成功,进入角色选择
            MessageBox.Show("注册成功,请登录", "提示", MessageBoxType.Information).OnYes = null;
            this.gameObject.SetActive(false);
            uiLogin.SetActive(true);
        }
        else
            MessageBox.Show(message, "错误", MessageBoxType.Error);
    }


}

二、服务端处理

客户端有UserService 服务端自然也要有

1.Uservice.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using Network;
using SkillBridge.Message;
//using GameServer.Entities;
using GameServer.Managers;

namespace GameServer.Services
{
    
    
    class UserService : Singleton<UserService>
    {
    
    

        public UserService()   //构造函数
        {
    
    
 
            MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<UserRegisterRequest>(this.OnRegister); //消息订阅,只要有注册消息来就执行相应的方法
            MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<UserLoginRequest>(this.OnLogin); //消息订阅,只要有登录消息来就执行相应的方法
   
        }


        public void Init()
        {
    
    

        }
        void OnLogin(NetConnection<NetSession> sender, UserLoginRequest request) //处理登录消息
        {
    
    
            Log.InfoFormat("用户登录响应:User:{0} Pass:{1}", request.User, request.Passward);

            NetMessage message = new NetMessage(); //创建网络响应消息
            message.Response = new NetMessageResponse();
            message.Response.userLogin = new UserLoginResponse();

            TUser user = DBService.Instance.Entities.Users.Where(u => u.Username == request.User).FirstOrDefault(); //这边用DBService简写了SQL语句,进行统一封装,效果其实还是那个效果
            //正常数据校验
            if(user.Username.Equals(request.User)&& user.Password.Equals(request.Passward)){
    
    
                message.Response.userLogin.Result = Result.Success; //校验成功就将结果设为成功
                message.Response.userLogin.Errormsg = "None";
            }
            else
            {
    
    
                message.Response.userLogin.Result = Result.Failed;//校验失败就将结果设为成功
                message.Response.userLogin.Errormsg = "账户名或者密码错误,请检查";//返回错误信息
            }

            byte[] data = PackageHandler.PackMessage(message); //将消息进行封包
            sender.SendData(data, 0, data.Length); //发送响应,回复客户端



        }
        //和登录的基本构造差不多
        void OnRegister(NetConnection<NetSession> sender, UserRegisterRequest request)
        {
    
    
            Log.InfoFormat("UserRegisterRequest: User:{0}  Pass:{1}", request.User, request.Passward);

            NetMessage message = new NetMessage();
            message.Response = new NetMessageResponse();
            message.Response.userRegister = new UserRegisterResponse();


            TUser user = DBService.Instance.Entities.Users.Where(u => u.Username == request.User).FirstOrDefault();
            if (user != null)
            {
    
    
                message.Response.userRegister.Result = Result.Failed;
                message.Response.userRegister.Errormsg = "用户已存在.";
            }
            else
            {
    
    
                TPlayer player = DBService.Instance.Entities.Players.Add(new TPlayer());
                DBService.Instance.Entities.Users.Add(new TUser() {
    
     Username = request.User, Password = request.Passward, Player = player });
                DBService.Instance.Entities.SaveChanges();
                message.Response.userRegister.Result = Result.Success;
                message.Response.userRegister.Errormsg = "None";
            }

            byte[] data = PackageHandler.PackMessage(message);
            sender.SendData(data, 0, data.Length);
        }

       
    }
}

总结

基本流程大概这样,ET框架基本上把底层封装好了,我们只需要调用相应的方法即可,简简单单,没有脑袋。

猜你喜欢

转载自blog.csdn.net/weixin_46172181/article/details/126456552
今日推荐