Zjh游戏(十二)登陆功能的实现

制作单线程

  • 在所有涉及到数据库的操作,全部使用单线程
  • 防止多个线程同时访问,从而造成数据错乱
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyServer
{
    public delegate void Executedelegate();
    /// <summary>
    /// 单线程类
    /// </summary>
    public class SingleExecute
    {
        private static object ob = new object();
        private static SingleExecute instacne;
        public static SingleExecute Instacne
        {
            get
            {
                lock (ob)
                {
                    if (instacne == null)
                    {
                        instacne = new SingleExecute();
                    }
                    return instacne;
                }
            }
        }

        private object objLock = new object();

        /// <summary>
        /// 互斥锁
        /// </summary>
        private Mutex mutex;

        public SingleExecute()
        {
            mutex = new Mutex();
        }

        /// <summary>
        /// 单线程执行逻辑
        /// </summary>
        public void Execute(Executedelegate executedelegate)
        {
            lock (objLock)
            {
                mutex.WaitOne();
                executedelegate();
                mutex.ReleaseMutex();
                
            }
        }
    }
}


数据库的操作

  • 判断是否在线
  • 判断用户名和密码是否一致
  • 判断用户名是否为空
  • 添加idClient字典,根据用户id查找client

数据库代码

using MyServer;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GameServer.DadaBase
{
    public class DatabaseManager
    {
        private static MySqlConnection sqlConnect;
        /// <summary>
        /// 根据ID保存Client的字典
        /// </summary>
        private static Dictionary<int, ClientPeer> idClientDic;
        public static void StartConnect()
        {
            idClientDic = new Dictionary<int, ClientPeer>();
            string conStr = "database=zjhgame;data source=127.0.0.1;port=3306;User=root;pwd=zhao19971225";
            sqlConnect = new MySqlConnection(conStr);
            sqlConnect.Open();//开启和数据库的连接
        }

        /// <summary>
        /// 判断该用户名是否存在数据库中
        /// </summary>
        public static bool IsExistUserName(string userName)
        {
            //查询命令
            MySqlCommand cmd = new MySqlCommand("select UserName from userinfo where UserName=@name", sqlConnect);
            //设置参数,填入参数
            cmd.Parameters.AddWithValue("name", userName);
            //开始查询
            MySqlDataReader reader = cmd.ExecuteReader();
            //是否存在
            bool result = reader.HasRows;
            //关闭查询
            reader.Close();
            return result;
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        public static void CreatUser(string userName,string pwd)
        {
            //创建命令
            MySqlCommand cmd = new MySqlCommand("insert into userinfo set UserName=@name,Password=@pwd,OnLine=0,IconName=@iconName",sqlConnect);
            //对参数进行赋值
            cmd.Parameters.AddWithValue("name",userName);
            cmd.Parameters.AddWithValue("pwd",pwd);
            Random random = new Random();
            int index= random.Next(0,19);
            cmd.Parameters.AddWithValue("iconName","headIcon_"+index.ToString());
            cmd.ExecuteNonQuery();//只执行不查询
        }

        /// <summary>
        /// 账号密码是否一致
        /// </summary>
        public static bool IsMatch(string userName,string pwd)
        {
            MySqlCommand cmd = new MySqlCommand("select * from userinfo where UserName=@name",sqlConnect);
            cmd.Parameters.AddWithValue("name",userName);
            //开始查询
            MySqlDataReader reader = cmd.ExecuteReader();
            if (reader.HasRows)//如果查询到了
            {
                reader.Read();//读取
                //读取Password的内容和传入的密码相判断
                bool result = reader.GetString("Password") == pwd;
                reader.Close();
                return result;
            }
            reader.Close();
            return false;
        }

        /// <summary>
        /// 是否在线
        /// </summary>
        public static bool IsOnline(string userName)
        {
            MySqlCommand cmd = new MySqlCommand("select OnLine from userinfo where UserName=@name",sqlConnect);
            cmd.Parameters.AddWithValue("name",userName);
            MySqlDataReader reader = cmd.ExecuteReader();
            if (reader.HasRows)
            {
                reader.Read();
                bool result = reader.GetBoolean("OnLine");
                reader.Close();
                return result;
            }
            reader.Close();
            return false;

        }

        /// <summary>
        /// 登陆上线
        /// </summary>
        public static void Login(string userName,ClientPeer client)
        {
            //更新在线状态
            MySqlCommand cmd = new MySqlCommand("update userinfo set OnLine=true where UserName=@name",sqlConnect);
            cmd.Parameters.AddWithValue("name",userName);
            cmd.ExecuteNonQuery();

            //获取ID和用户名
            MySqlCommand cmd1 = new MySqlCommand("select * from userinfo where UserName=@name",sqlConnect);
            cmd1.Parameters.AddWithValue("name",userName);
            MySqlDataReader reader = cmd1.ExecuteReader();
            if (reader.HasRows)
            {
                reader.Read();
                int Id = reader.GetInt32("ID");
                client.id = Id;
                client.userName = userName;
                if (!idClientDic.ContainsKey(Id))
                    idClientDic.Add(Id,client);
                reader.Close();
            }
            reader.Close();
        }

        /// <summary>
        /// 根据UserID获得Client
        /// </summary>
        public static ClientPeer GetClientBuyUserId(int id)
        {
            if (idClientDic.ContainsKey(id))
            {
                return idClientDic[id];
            }
            return null;
        }
    }
}



接收客户端登陆请求的处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GameServer.DadaBase;
using MyServer;
using Protocol.Code;
using Protocol.Dto;

namespace GameServer.Logic
{
    /// <summary>
    /// 账号模块的处理
    /// </summary>
    public class AccountHandler : IHandler
    {
        public void DisConnected(ClientPeer clientPeer)
        {

        }

        public void Receive(ClientPeer client, int subCode, object value)
        {
            switch (subCode)
            {
                case AccountCode.Register_CREQ:
                    Register(client,value as AccountDto);
                    break;
                case AccountCode.Login_CREQ:
                    Login(client,value as AccountDto);
                    break;
            }
        }

        /// <summary>
        /// 客户端请求登陆的处理
        /// </summary>
        private void Login(ClientPeer client, AccountDto dto)
        {
            SingleExecute.Instacne.Execute(()=> 
            {
                if (DatabaseManager.IsExistUserName(dto.userName)==false)
                {
                    //用户名不存在
                    client.SendMsg(OpCode.Account, AccountCode.LOgin_SRES, -1);
                    return;
                }
                if (DatabaseManager.IsMatch(dto.userName,dto.password)==false)
                {
                    //账号密码不匹配
                    client.SendMsg(OpCode.Account, AccountCode.LOgin_SRES, -2);
                    return;
                }
                if (DatabaseManager.IsOnline(dto.userName))
                {
                    //当前用户已在线
                    client.SendMsg(OpCode.Account, AccountCode.LOgin_SRES, -3);
                    return;
                }
                DatabaseManager.Login(dto.userName,client);
                //登陆成功
                client.SendMsg(OpCode.Account, AccountCode.LOgin_SRES, 0);
            });
        }

        /// <summary>
        ///客户端注册请求的处理
        /// </summary>
        private void Register(ClientPeer client, AccountDto dto)
        {
            ///单线程执行
            ///作用:防止多个线程同时访问,数据错乱
            SingleExecute.Instacne.Execute(()=> 
            {
                //判断数据库中是否存在该用户,存在就给客户端返回-1
                if (DatabaseManager.IsExistUserName(dto.userName))
                {
                    client.SendMsg(OpCode.Account, AccountCode.Register_SRES, -1);
                    return;
                }
                //判断数据库中是否存在该用户,不存在就创建该用户并给客户端返回0
                DatabaseManager.CreatUser(dto.userName, dto.password);
                client.SendMsg(OpCode.Account, AccountCode.Register_SRES, 0);
            });
           
        }
    }
}


客户端处理服务器登陆请求后的回应

using Protocol.Code;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AccountHandler : BaseHandler
{
    
    public override void OnReceive(int subCode, object value)
    {
        switch (subCode)
        {
            case AccountCode.Register_SRES:
                Register_SRES((int)value);
                break;
            case AccountCode.LOgin_SRES:
                Login_SRES((int)value);
                break;
        }
    }

    /// <summary>
    /// 处理服务器端注册后的回应
    /// </summary>
    private void Register_SRES(int value)
    {
        if (value==-1)
        {
            EventCenter.Broadcast(EventDefine.Hint,"该用户已经被注册");
            return;
        }
        if (value==0)
        {
            EventCenter.Broadcast(EventDefine.Hint, "注册成功");
        }
    }

    /// <summary>
    ///  处理服务器端登陆后的回应
    /// </summary>
    private void Login_SRES(int value)
    {
        Debug.Log(value);
        switch (value)
        {
            case -3:
                EventCenter.Broadcast(EventDefine.Hint, "当前用户已在线");
                break;              
            case -2:
                EventCenter.Broadcast(EventDefine.Hint, "账号密码不匹配");
                break;
            case -1:
                EventCenter.Broadcast(EventDefine.Hint, "用户名不存在");
                break;
            case 0:
                EventCenter.Broadcast(EventDefine.Hint, "登陆成功");
                break;
        }
    }
}


有需要学习视频的欢迎关注微信公众号:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值