主页 > 人工智能  > 

Unity-TCP-网络聊天功能(二):登录与注册

Unity-TCP-网络聊天功能(二):登录与注册
5.客户端实现注册与登录接口

创建好UI

接下来定义发给客户端的协议等

public class MessageHelper { //发送登录的消息给服务器 1002 public void SendLoginMsg(string account, string pwd) { LoginMsgC2S msg = new LoginMsgC2S(); msg.account = account; msg.password = pwd; var str = JsonHelper.ToJson(msg);//json格式化注册请求 SendToServer(1002, str);//发送 } public Action<LoginMsgS2C> loginHandle; //处理登录(结果)请求 private void LoginMsgHandle(byte[] obj) { var str = Encoding.UTF8.GetString(obj);//将接受的消息从字节转换为string LoginMsgS2C msg = JsonHelper.ToObject<LoginMsgS2C>(str);//在从json格式的string转为对应LoginMsgS2C loginHandle?.Invoke(msg);//如果处理注册消息的事件有订阅,就执行。 } //发送聊天信息给服务器 public void SendChatMsg(string account, string chat) { ChatMsgC2S msg = new ChatMsgC2S(); msg.player = account; msg.msg = chat; msg.type = 0; var str = JsonHelper.ToJson(msg);//json格式化注册请求 SendToServer(1003, str);//发送 } public Action<ChatMsgS2C> chatHandle; //处理聊天(转发)请求 private void ChatMsgHandle(byte[] obj) { var str = Encoding.UTF8.GetString(obj);//将接受的消息从字节转换为string ChatMsgS2C msg = JsonHelper.ToObject<ChatMsgS2C>(str);//在从json格式的string转为对应ChatMsgS2C chatHandle?.Invoke(msg);//如果处理注册消息的事件有订阅,就执行。 } //发送注册的消息给服务器 1001 public void SendRegisterMsg(string account, string email, string pwd) { RegisterMsgC2S msg = new RegisterMsgC2S(); msg.account = account; msg.email = email; msg.password = pwd; var str = JsonHelper.ToJson(msg);//json格式化注册请求 SendToServer(1001, str);//发送 } public Action<RegisterMsgS2C> registerHandle; //处理注册(结果)请求 private void RigisterMsgHandle(byte[] obj) { var str = Encoding.UTF8.GetString(obj);//将接受的消息从字节转换为string RegisterMsgS2C msg = JsonHelper.ToObject<RegisterMsgS2C>(str);//在从json格式的string转为对应RegisterMsgS2C registerHandle?.Invoke(msg);//如果处理注册消息的事件有订阅,就执行。 } } //1002 public class LoginMsgC2S { public string account; public string password; } public class LoginMsgS2C { public string account; public string password; public int result;//0成功 1失败:账号或密码错误 } //1001 public class RegisterMsgC2S { public string account; public string email; public string password; } public class RegisterMsgS2C { public string account; public string email; public string password; public int result;//0成功 1失败:已被注册的账号 } //1003 public class ChatMsgC2S { public string player; public string msg; public int type;//0世界聊天 } //服务器转发给所有在线的客户端 public class ChatMsgS2C { public string player; public string msg; public int type;//0世界聊天 }

创建Unity-Scripts/View/LoginView.cs和ChatView.cs

逻辑:LoginView用于UI界面按钮控制,调用MessageHelper里面的方法,发送和处理消息

public class LoginView : MonoBehaviour { private GameObject register; //注册相关 private Button registerBtn; private InputField usernameInput_Register; private InputField emailInput_Register; private InputField passwordInput_Register; private Button registerBtn_Register; private Button closeBtn_Register; //登录相关 private Button loginBtn; private InputField usernameInput_Login; private InputField passwordInput_Login; // Start is called before the first frame update void Start() { register = transform.Find("Register").gameObject; //打开注册界面 registerBtn = transform.Find("RegisterBtn").GetComponent<Button>(); registerBtn.onClick.AddListener(OpenRegisterView); //关闭注册界面 closeBtn_Register = transform.Find("Register/CloseBtn").GetComponent<Button>(); closeBtn_Register.onClick.AddListener(CloseRegisterView); //注册界面输入框 usernameInput_Register = transform.Find("Register/UsernameInput/InputField").GetComponent<InputField>(); emailInput_Register = transform.Find("Register/EmailInput/InputField").GetComponent<InputField>(); passwordInput_Register = transform.Find("Register/PasswordInput/InputField").GetComponent<InputField>(); //注册界面-注册按钮 registerBtn_Register = transform.Find("Register/RegisterBtn").GetComponent<Button>(); registerBtn_Register.onClick.AddListener(RegisterOnClick); //登录界面-登录按钮 loginBtn = transform.Find("LoginBtn").GetComponent<Button>(); loginBtn.onClick.AddListener(LoginOnClick); usernameInput_Login = transform.Find("UsernameInput/InputField").GetComponent<InputField>(); passwordInput_Login = transform.Find("PasswordInput/InputField").GetComponent<InputField>(); //处理登录结果 MessageHelper.Instance.loginHandle += LoginHandle; MessageHelper.Instance.registerHandle += RegisterHandle; } // Update is called once per frame void Update() { } private void CloseRegisterView() { register.gameObject.SetActive(false); } private void OpenRegisterView() { register.gameObject.SetActive(true); } private void LoginHandle(LoginMsgS2C obj) { if (obj.result == 0) { //登录成功将用户信息和返回的用户信息绑定起来,使用PlayerData类 PlayerData.Instance.LoginMsgS2C = obj; Debug.Log("登陆成功"); //this.gameObject.SetActive(false); Destroy(this.gameObject); var chatView = Resources.Load<GameObject>("ChatView"); var chatObj = GameObject.Instantiate<GameObject>(chatView); chatObj.AddComponent<ChatView>(); } else { Tips($"登录失败,错误码:{obj.result}"); } } private void RegisterHandle(RegisterMsgS2C obj) { if (obj.result == 0) { Debug.Log("注册成功"); Tips("注册成功"); register.gameObject.SetActive(false); usernameInput_Login.text = obj.account; passwordInput_Login.text = obj.password; } else { Tips($"注册失败,错误码:{obj.result}"); } } private void LoginOnClick() { if (string.IsNullOrEmpty(usernameInput_Login.text)) { Tips("请输入账号!!!"); return; } if (string.IsNullOrEmpty(passwordInput_Login.text)) { Tips("请输入邮箱!!!"); return; } //发送数据给服务器 MessageHelper.Instance.SendLoginMsg(usernameInput_Login.text, passwordInput_Login.text); } private void RegisterOnClick() { if (string.IsNullOrEmpty(usernameInput_Register.text)) { Tips("请输入账号!!!"); return; } if (string.IsNullOrEmpty(emailInput_Register.text)) { Tips("请输入邮箱!!!"); return; } if (string.IsNullOrEmpty(passwordInput_Register.text)) { Tips("请输入密码!!!"); return; } //发送数据给服务器 MessageHelper.Instance.SendRegisterMsg(usernameInput_Register.text, emailInput_Register.text, passwordInput_Register.text); } private GameObject _tipsObj; public void Tips(string str) { if (_tipsObj != null) { GameObject.Destroy(_tipsObj); } var tipsItem = transform.Find("TipsItem").gameObject; _tipsObj = GameObject.Instantiate<GameObject>(tipsItem); _tipsObj.transform.SetParent(this.transform, false); var content = _tipsObj.transform.Find("Text").GetComponent<Text>(); content.text = str; _tipsObj.gameObject.SetActive(true); GameObject.Destroy(_tipsObj, 1.5f); } private void OnDestroy() { MessageHelper.Instance.loginHandle -= LoginHandle; MessageHelper.Instance.registerHandle -= RegisterHandle; } }

创建Unity-Scripts/PlayerData.cs

public class PlayerData { private static PlayerData instance = new PlayerData(); public static PlayerData Instance => instance; public LoginMsgS2C LoginMsgS2C; }

测试运行。

6.服务端处理注册与登录业务

将Unity MessageHelper里的消息类C2S、S2C等复制到Server-MessageHelper中

class MessageHelper { } //1002 public class LoginMsgC2S { public string account; public string password; } public class LoginMsgS2C { public string account; public string password; public int result;//0成功 1失败:账号或密码错误 } //1001 public class RegisterMsgC2S { public string account; public string email; public string password; } public class RegisterMsgS2C { public string account; public string email; public string password; public int result;//0成功 1失败:已被注册的账号 } //1003 public class ChatMsgC2S { public string player; public string msg; public int type;//0世界聊天 } //服务器转发给所有在线的客户端 public class ChatMsgS2C { public string player; public string msg; public int type;//0世界聊天 }

Server-Client理论上需要进入数据库判断有无账号,然后处理业务,这里用一个类Server/PlayerData.cs缓存这些数据,不用数据库了

namespace Server { internal class PlayerData { private static PlayerData instance = new PlayerData(); public static PlayerData Instance => instance;//单例 Dictionary<string, RegisterMsgS2C> userMsg = new Dictionary<string, RegisterMsgS2C>();//缓存注册信息 //注册后,result=0表示注册成功,将这个注册后的信息返回给客户端 public RegisterMsgS2C Add(RegisterMsgC2S msgC2S) { var item = new RegisterMsgS2C(); userMsg[msgC2S.account] = item; item.account = msgC2S.account; item.password = msgC2S.password; item.result = 0; return item; } //判断是否存在相同的账号 public bool Contain(string account) { return userMsg.ContainsKey(account); } //维护已经登陆的用户 Dictionary<string, Client> LoginUser = new Dictionary<string, Client>(); public void AddLoginUser(string account, Client client) { LoginUser[account] = client; } public Dictionary<string, Client> GetAllLoginUser() { return LoginUser; } } } //处理注册请求 private void RegisterMsgHandle(byte[] obj) { var msg = JsonHelper.ToObject<RegisterMsgC2S>(obj); RegisterMsgS2C response = null; if (PlayerData.Instance.Contain(msg.account)) { response = new RegisterMsgS2C(); response.result = 1;//已经包含该帐号了 } else { response = PlayerData.Instance.Add(msg); } SendToClient(1001, JsonHelper.ToJson(response)); } //处理登录请求 private void LoginMsgHandle(byte[] obj) { //判断账号和密码是否跟缓存的一直,如果是,返回账号和密码 var msg = JsonHelper.ToObject<LoginMsgC2S>(obj); LoginMsgS2C response = new LoginMsgS2C(); if (PlayerData.Instance.Contain(msg.account)) { response.result = 0;//已包含该账号 response.account = msg.account; response.password = msg.password; //将用户储存起来 PlayerData.Instance.AddLoginUser(msg.account, this); } else { response.result = 1;//账号或密码错误 } SendToClient(1002, JsonHelper.ToJson(response)); }

运行测试,表明服务器收到了Unity客户端的注册信息后,在PlayerData中检测没有账号后,注册了一条数据,并返回给Unity客户端注册成功

再次注册同样的数据,表示注册失败,返回result = 1

用刚刚的账号登录,就登录成功了

为什么Unity和Server的输出都是乱码呢,因为直接输出的是包体大小+协议id+包体,所以前面是乱码,只输出包体就不会乱码,一下为修改了在send和receive时只输出body内容,输出内容正常。

标签:

Unity-TCP-网络聊天功能(二):登录与注册由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Unity-TCP-网络聊天功能(二):登录与注册