[Extreme] P4 network message processing_communication and protocol (client communication)


foreword

完成项目的注册登录系统,了解与服务器进行交互以及数据校验,为了方面这边就用注释的方式来阐述。
insert image description here


1. UI preparation

The UI for registration and login depends on personal preferences. Basically, the input is only a few pieces. I will simply demonstrate it here, mainly in the form of code comments, which is more humanized

Login
insert image description here
Register
insert image description here

2. Client logic script writing

In order to reduce coupling, login here is a script, register is a script, and mount it on the corresponding UI component

UserService handles UI layer transfer parameters for logical processing

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. Login script

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. Registration script

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);
    }


}

2. Server-side processing

The client has UserService, and the server naturally also has

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);
        }

       
    }
}

Summarize

The basic process is roughly like this. The ET framework basically encapsulates the bottom layer. We only need to call the corresponding method, which is simple and brainless.

Guess you like

Origin blog.csdn.net/weixin_46172181/article/details/126456552