Server-基于Sokcet(C#)长连接架构游戏服务器+数据库表结构设计

学前必读
https://blog.csdn.net/zhanxxiao/article/details/106819756

由于项目需要,公司的后端迟迟无法就位,自己便利用 C# 搭建了一套简单的服务器项目。
整个服务器的框架使用到 MVC 设计思想:
涉及到的系统有:
登录、注册、房间等
废话不多说,上代码了

1、客户端和服务器共享工程
在这里插入图片描述

namespace ShareProject
{
    /// <summary>
    /// 服务器与客户端通讯协议
    /// </summary>
    public enum ActionCode
    {
        None,           //默认为null不处理
        Login,          //登录
        Register,       //注册
        ListRoom,       //房间列表集合
        CreateRoom,     //创建房间
        JoinRoom,       //加入房间
        UpdateRoom,     //更新房间状态
        QuitRoom,       //退出房间
        StartGame,      //开始游戏
        ShowTimer,      //显示倒计时
        StartPlay,      //进入游戏
        Move           //移动
    }
}
/// <summary>
/// 客户端请求
/// </summary>
namespace ShareProject
{
    /// <summary>
    /// 客户端请求
    /// </summary>
    public enum RequestCode
    {
        None,   //默认为null
        User,   //用户请求
        Room,   //房间请求
        Game    //游戏进行中请求
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace ShareProject
{
    /// <summary>
    /// 执行状态
    /// </summary>
    public enum ReturnCode
    {
        Success,
        Fail,
        NotFound
    }
}
using System;
using System.Collections.Generic;
using System.Text;

/// <summary>
/// 角色类型
/// </summary>
namespace ShareProject
{
    public enum RoleType
    {
        Blue,
        Red
    }
}

接下来就是我们的服务器核心的代码:如果下图所示,依次共享源码:
在这里插入图片描述

using MySql.Data.MySqlClient;
using ServerFrameworkProject.Model;
using ServerFrameworkProject.Servers;
using ServerFrameworkProject.Tool;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 客户端集合
/// </summary>
namespace ServerFrameworkProject
{
    class Client
    {
        public Socket clientSocket;
        private Server server;
        private Message msg = new Message();
        private MySqlConnection mysqlConn;
        private Room room;
        //用户
        private User user;

        /// <summary>
        /// 房间
        /// </summary>
        public Room Room
        {
            get
            {
                return room;
            }
            set
            {
                room = value;
            }
        }

        public MySqlConnection MYSQLConn
        {
            get
            {
                return mysqlConn;
            }
        }

        //设置数据
        public void SetUserData(User user)
        {
            this.user = user;
        }

        public int GetUserID()
        {
            return user.id;
        }

        //获取数据
        public string GetUserData()
        {
            //组拼字符串
            return user.id + "," + user.userName + "," ;
        }
        
        
        public Client()
        {

        }

        public Client(Socket clientSocket, Server server)
        {
            this.clientSocket = clientSocket;
            this.server = server;
            mysqlConn = ConnHelper.Connect();
        }

        /// <summary>
        /// 开启监听
        /// </summary>
        public void Start()
        {
            if (clientSocket == null || clientSocket.Connected == false)
            {
                Console.WriteLine("客户端连接已断开..." + "当前在线客户端个数:");
                return;
            }
            //开启接收
            clientSocket.BeginReceive(msg.Data, msg.StartIndex, msg.RemainSize, SocketFlags.None, ReceiveCallBack, null);
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="ar"></param>
        private void ReceiveCallBack(IAsyncResult ar)
        {
            try
            {
                if (clientSocket == null || clientSocket.Connected == false)
                {
                    Console.WriteLine(clientSocket.Connected + "客户端已退出");
                    return;
                }
                //接收数据的长度
                int count = clientSocket.EndReceive(ar);
                if (count == 0)
                {
                    //断开连接
                    CloseConnect();
                }
                //todo 处理接收到的数据、count 为新消息的数量
                msg.ReadMessage(count, OnProcessMessage);
                Start();
            }
            catch (Exception e)
            {
                Console.WriteLine("异常信息" + e);
                CloseConnect();
            }
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="requestCode"></param>
        /// <param name="actionCode"></param>
        /// <param name="data"></param>
        private void OnProcessMessage(RequestCode requestCode, ActionCode actionCode, string data)
        {
            server.HandleRequest(requestCode, actionCode, data, this);
        }


        /// <summary>
        /// 关闭连接
        /// </summary>
        private void CloseConnect()
        {
            //关闭跟客户端的连接
            ConnHelper.CloseConnection(mysqlConn);
            if (clientSocket != null)
            {
                Console.WriteLine(clientSocket.Connected + "客户端已断开");
                //关闭 socket
                clientSocket.Close();
            }
            //如果不在任何房间
            if (room != null)
            {
                room.QuitRoom(this);
            }
            server.RemoveClient(this);
        }

        /// <summary>
        /// 数据包装
        /// </summary>
        /// <param name="actionCode"></param>
        /// <param name="data"></param>
        public void Send(ActionCode actionCode, string data)
        {
            try
            {
                //需要传输的数据
                byte[] bytes = Message.PackData(actionCode, data);
                clientSocket.Send(bytes);
            }
            catch (Exception e)
            {
                Console.WriteLine("客户端已离去:" + e);
            }
        }


        /// <summary>
        /// 判断自身是否为房主
        /// </summary>
        /// <returns></returns>
        public bool IsHouseOwner()
        {
            return room.IsHouseOwner(this);
        }

    }
}
using ServerFrameworkProject.Servers;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 抽象控制基类
    /// </summary>
    class BaseController : IBaseController
    {
        protected RequestCode requestCode = RequestCode.None;

        public RequestCode RequestCode
        {
            get
            {
                return requestCode;
            }
        }

        /// <summary>
        /// 默认请求、没有指定 ActionCode的时候
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public virtual string DefaultHandle(string data, Client client, Server server)
        {
            //不给客户端返回任何东西
            return null;
        }
    }
}
using ServerFrameworkProject.Servers;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 控制器管理者
    /// </summary>
    class ControllerManager
    {
        //存储 controller
        private Dictionary<RequestCode, BaseController> controllerDic = new Dictionary<RequestCode, BaseController>();
        private Server server;

        public ControllerManager(Server server)
        {
            this.server = server;
            InitController();
        }

        /// <summary>
        /// 初始化所有的控制器
        /// </summary>
        private void InitController()
        {
            DefaultController defaultController = new DefaultController();
            controllerDic.Add(defaultController.RequestCode, defaultController);
            controllerDic.Add(RequestCode.User, new UserController());
            controllerDic.Add(RequestCode.Room, new RoomController());
            controllerDic.Add(RequestCode.Game, new GameController());
        }

        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="requestCode"></param>
        /// <param name="actionCode"></param>
        public void HandleRequest(RequestCode requestCode, ActionCode actionCode, string data, Client client)
        {
            //通过requestCode找到对应的 BaseController
            BaseController controller;
            bool isGet = controllerDic.TryGetValue(requestCode, out controller);
            if (isGet == false)
            {
                Console.WriteLine("无法获取[" + requestCode + "]对应的 Controller,无法处理请求");
                return;
            }
            //处理请求、通过反射调用 Ctrl 得到方法
            //枚举类型转字符串
            string methodName = Enum.GetName(typeof(ActionCode), actionCode);
            //根据方法名得到方法信息
            MethodInfo mi = controller.GetType().GetMethod(methodName);
            if (mi == null)
            {
                Console.WriteLine("[警告]在 Controller[" + controller.GetType() + "] 中没有对应的处理方法:[" + methodName + "]");
            }
            object[] parameters = new object[] { data, client, server };
            //如果 MethodInfo 存在、调用 methodName
            object obj = mi.Invoke(controller, parameters);
            //obj 为空或者为空字符串
            if (obj == null || string.IsNullOrEmpty(obj as string))
            {
                return;
            }
            //向客户端发起响应、obj为返回的数据
            server.SendResponse(client, actionCode, obj as string);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 默认处理
    /// </summary>
    class DefaultController:BaseController
    {
        public DefaultController()
        {

        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ServerFrameworkProject.Servers;
using ShareProject;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 游戏逻辑控制者
    /// </summary>
    class GameController:BaseController
    {
        public GameController()
        {
            requestCode = RequestCode.Game;
        }

        /// <summary>
        /// 开始游戏按钮处理
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string StartGame(string data, Client client, Server server)
        {
            Console.WriteLine("等待房主开始游戏...");
            //是房主的时候
            if (client.IsHouseOwner())
            {
                Console.WriteLine("房主正在开始游戏...");
                Room room = client.Room;
                //消息广播
                room.BroadCastMessage(client, ActionCode.StartGame, ((int)ReturnCode.Success).ToString());
                //开始计时
                room.ShowTimer();
                return ((int)ReturnCode.Success).ToString();
            }
            else
            {
                Console.WriteLine("您不是房主,无法开始游戏");
                return ((int)ReturnCode.Fail).ToString();
            }
        }


        /// <summary>
        /// 同步位置
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string Move(string data, Client client, Server server)
        {
            Console.WriteLine("开始移动");
            //得到房间给其他人发送消息
            Room room = client.Room;
            if (room != null)
            {
                //发送消息到其他客户端
                room.BroadCastMessage(client, ActionCode.Move, data);
            }
            //当前客户端无需响应
            return null;
        }
    }
}

using ServerFrameworkProject.Servers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 默认处理接口方法
    /// </summary>
    interface IBaseController
    {
        string DefaultHandle(string data, Client client, Server server);
    }
}

using ServerFrameworkProject.Servers;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 房间处理
    /// </summary>
    class RoomController:BaseController
    {
        public RoomController()
        {
            requestCode = RequestCode.Room;
        }


        public string CreateRoom(string data, Client client, Server server)
        {
            Console.WriteLine("房主创建房间成功");
            //创建房间
            server.CreateRoom(client);
            //返回成功以及角色类型、默认房主为蓝色
            return ((int)ReturnCode.Success).ToString() + "," + ((int)RoleType.Blue).ToString();
            //return ((int)ReturnCode.Success).ToString();
        }


        /// <summary>
        /// 房间列表信息
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string ListRoom(string data, Client client, Server server)
        {
            Console.WriteLine("房间当前玩家信息...");
            //组拼房间信息
            StringBuilder stringBuilder = new StringBuilder();
            foreach (Room room in server.GetRommList())
            {
                //判断房间状态
                if (room.IsWaitingJoin())
                {
                    //房间信息添加
                    stringBuilder.Append(room.GetHouseOwnerDara() + "|");
                }
            }
            //空字符串
            if (stringBuilder.Length == 0)
            {
                stringBuilder.Append("0");
            }
            else
            {
                //有数据
                stringBuilder.Remove(stringBuilder.Length - 1, 1);
            }
            return stringBuilder.ToString();
        }


        /// <summary>
        /// 加入房间
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string JoinRoom(string data, Client client, Server server)
        {
            Console.WriteLine("玩家正在加入房间...");
            //根据 id 查找房间
            int id = int.Parse(data);
            Room room = server.GetRoomByID(id);
            //没有找到房间、失败
            if (room == null)
            {
                Console.WriteLine("房间已经销毁了");
                return ((int)ReturnCode.NotFound).ToString();
            }
            else if (room.IsWaitingJoin() == false)
            {
                Console.WriteLine("房间已经满员");
                //是否可以进行加入
                return ((int)ReturnCode.Fail).ToString();
            }
            else
            {
                Console.WriteLine("加入成功");
                //成功
                room.AddClient(client);
                //所有信息返回
                string roomdata = room.GetRoomData();
                //当前客户端清除、不包含 returncode                                   returnCode,roomType -  id,usernmae,totalCount,winCount|username,totalCount,winCount
                room.BroadCastMessage(client, ActionCode.UpdateRoom, roomdata);
                //return ((int)ReturnCode.Success).ToString() + "-" + roomdata;
                return ((int)ReturnCode.Success).ToString() + "," + ((int)RoleType.Red).ToString() + "-" + roomdata;
            }
        }

        /// <summary>
        /// 退出房间
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string QuitRoom(string data, Client client, Server server)
        {
            Console.WriteLine("玩家退出房间...");
            bool isHouseOwner = client.IsHouseOwner();
            Room room = client.Room;
            //是房主
            if (isHouseOwner)
            {
                Console.WriteLine("房主退出");
                //向其他的客户端发出消息
                room.BroadCastMessage(client, ActionCode.QuitRoom, ((int)ReturnCode.Success).ToString());
                //退出
                room.Close();

                //处理房主退出
                return ((int)ReturnCode.Success).ToString();
                //销毁房间
            }
            else
            {
                Console.WriteLine("用户退出");
                //不是房主、移除
                client.Room.RemoveClient(client);
                room.BroadCastMessage(client, ActionCode.UpdateRoom, room.GetRoomData());
                //通知其他客户端
                return ((int)ReturnCode.Success).ToString();
            }
        }
    }
}

using MySqlX.XDevAPI.Common;
using ServerFrameworkProject.DAO;
using ServerFrameworkProject.Model;
using ServerFrameworkProject.Servers;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace ServerFrameworkProject.Controller
{
    /// <summary>
    /// 用户控制者
    /// </summary>
    class UserController:BaseController
    {
        private UserDAO userDAO = new UserDAO();

        public UserController()
        {
            requestCode = RequestCode.User;
        }

        /// <summary>
        /// 登录请求
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string Login(string data, Client client, Server server)
        {
            Console.WriteLine("登录中....");
            string[] strs = data.Split(',');
            User user = userDAO.VerifyUser(client.MYSQLConn, strs[0], strs[1]);
            if (user == null)
            {
                Console.WriteLine("登录失败");
                Enum.GetName(typeof(ReturnCode), ReturnCode.Fail);
                return ((int)ReturnCode.Fail).ToString();
            }
            else
            {
                Console.WriteLine("登录成功");
                //登录成功处理请求信息
                //Result result = resultDAO.GetResultByUserID(client.MYSQLConn, user.id);
                //登录账号保存
                client.SetUserData(user);
                return string.Format("{0},{1}", ((int)ReturnCode.Success).ToString(), user.userName);
            }
        }

        /// <summary>
        /// 注册请求
        /// </summary>
        /// <param name="data"></param>
        /// <param name="client"></param>
        /// <param name="server"></param>
        /// <returns></returns>
        public string Register(string data, Client client, Server server)
        {
            Console.WriteLine("客户端请求注册");
            string[] strs = data.Split(',');
            string username = strs[0];
            string password = strs[1];
            bool res = userDAO.GetUserByUserName(client.MYSQLConn, username);
            //得到了用户名重复
            if (res)
            {
                Console.WriteLine("用户名重复");
                return ((int)ReturnCode.Fail).ToString();
            }
            //注册添加
            userDAO.AddUser(client.MYSQLConn, username, password);
            return ((int)ReturnCode.Success).ToString();
        }
    }
}
using MySql.Data.MySqlClient;
using ServerFrameworkProject.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.DAO
{
    class UserDAO
    {
        /// <summary>
        /// 校验
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public User VerifyUser(MySqlConnection conn, string username, string password)
        {
            MySqlDataReader reader = null;
            try
            {
                MySqlCommand cmd = new MySqlCommand("select * from user where username = @username and password= @password", conn);
                cmd.Parameters.AddWithValue("username", username);
                cmd.Parameters.AddWithValue("password", password);
                reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    int id = reader.GetInt32("id");
                    User user = new User(id, username, password);
                    return user;
                }
                else
                {
                    return null;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("在VerifyUser 的时候出现异常");
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return null;
        }

        /// <summary>
        /// 根据用户名查找 是否查找到用户数据
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="username"></param>
        /// <returns></returns>
        public bool GetUserByUserName(MySqlConnection conn, string username)
        {
            MySqlDataReader reader = null;
            try
            {
                MySqlCommand cmd = new MySqlCommand("select * from user where username = @username", conn);
                cmd.Parameters.AddWithValue("username", username);
                reader = cmd.ExecuteReader();
                //是否有数据
                if (reader.HasRows)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("在GetUserByUserName 的时候出现异常");
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
            return false;
        }


        /// <summary>
        /// 往数据库添加
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public void AddUser(MySqlConnection conn, string username, string password)
        {
            try
            {
            //防止 SQL 注入
                MySqlCommand cmd = new MySqlCommand("insert into user set username = @username , password = @password", conn);
                cmd.Parameters.AddWithValue("username", username);
                cmd.Parameters.AddWithValue("password", password);
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                Console.WriteLine("在AddUser 的时候出现异常");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Model
{
    public class Result
    {
        public int id { get; set; }
        public int userId { get; set; }
        public int totalCount { get; set; }
        public int winCount { get; set; }

        public Result(int id, int userId, int totalCount, int wincount)
        {
            this.id = id;
            this.userId = userId;
            this.totalCount = totalCount;
            this.winCount = wincount;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Model
{
    class User
    {
        public int id { get; set; }
        public string userName { get; set; }
        public string passWord { get; set; }
        public User(int id, string username, string passwod)
        {
            this.id = id;
            this.userName = username;
            this.passWord = passwod;
        }
    }
}

using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Servers
{
    /// <summary>
    /// 消息处理
    /// </summary>
    class Message
    {
        private byte[] data = new byte[1024];
        private int startIndex = 0;//我们存取了多少个字节的数据在数组里面

        //public void AddCount(int count)
        //{
        //    startIndex += count;
        //}
        public byte[] Data
        {
            get { return data; }
        }
        public int StartIndex
        {
            get { return startIndex; }
        }
        public int RemainSize
        {
            get { return data.Length - startIndex; }
        }

        /// <summary>
        /// 解析数据或者叫做读取数据
        /// </summary>
        public void ReadMessage(int newDataAmount, Action<RequestCode, ActionCode, string> processDtaCallBack)
        {
            //更新
            startIndex += newDataAmount;
            while (true)
            {
                if (startIndex <= 4) return;
                int count = BitConverter.ToInt32(data, 0);
                if ((startIndex - 4) >= count)
                {
                    //Console.WriteLine(startIndex);
                    //Console.WriteLine(count);
                    //string s = Encoding.UTF8.GetString(data, 4, count);
                    //Console.WriteLine("解析出来一条数据:" + s);

                    //先解析 request 
                    RequestCode requestCode = (RequestCode)BitConverter.ToInt32(data, 4);
                    ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 8);
                    //解析数据
                    string s = Encoding.UTF8.GetString(data, 12, count - 8); // 剩余数据字节长度
                    //回调函数
                    processDtaCallBack(requestCode, actionCode, s);

                    Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
                    startIndex -= (count + 4);
                }
                else
                {
                    break;
                }
            }
        }

        //数据包装
        public static byte[] PackData(ActionCode actionCode, string data)
        {
            //枚举、data 转换字节数组
            byte[] requestCodeBytes = BitConverter.GetBytes((int)actionCode);
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);
            //获取数据长度
            int dataAmount = requestCodeBytes.Length + dataBytes.Length;
            byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
            //组装
            byte[] newBytes = dataAmountBytes.Concat(requestCodeBytes).ToArray<byte>();
            return newBytes.Concat(dataBytes).ToArray<byte>();
        }


        //public static byte[] packdata(actioncode actioncode, string data)
        //{
        //    byte[] requestcodebytes = bitconverter.getbytes((int)actioncode);
        //    byte[] databytes = encoding.utf8.getbytes(data);
        //    int dataamount = requestcodebytes.length + databytes.length;
        //    byte[] dataamountbytes = bitconverter.getbytes(dataamount);
        //    byte[] newbytes = dataamountbytes.concat(requestcodebytes).toarray<byte>();//concat(databytes);
        //    return newbytes.concat(databytes).toarray<byte>();
        //}
    }
}

using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Servers
{
    /// <summary>
    /// 房间状态
    /// </summary>
    public enum RoomState
    {
        WaitingJoin,
        WaitingBattle,
        Battle,
        End
    }


    class Room
    {
        //当前房间所有的客户端
        private List<Client> clientRoom = new List<Client>();
        private RoomState roomState = RoomState.WaitingJoin;
        private Server server;

        public Room(Server server)
        {
            this.server = server;
        }

        //添加玩家
        public void AddClient(Client client)
        {
            //第一个为创建者、管理者
            clientRoom.Add(client);
            //访问房间
            client.Room = this;
            //大于最大人数
            if (clientRoom.Count >= 2)
            {
                //等待战斗
                roomState = RoomState.WaitingBattle;
            }
        }

        //移除
        public void RemoveClient(Client client)
        {
            client.Room = null;
            clientRoom.Remove(client);
            //修改房间状态
            //大于最大人数
            if (clientRoom.Count >= 2)
            {
                //等待战斗
                roomState = RoomState.WaitingBattle;
            }
            else
            {
                //等待加入
                roomState = RoomState.WaitingJoin;
            }
        }

        //房间是否在等待
        public bool IsWaitingJoin()
        {
            return roomState == RoomState.WaitingJoin;
        }

        //得到房主信息、集合中的第一个
        public string GetHouseOwnerDara()
        {
            return clientRoom[0].GetUserData();
        }



        //得到房间 ID
        public int GetID()
        {
            //房间是否为空
            if (clientRoom.Count > 0)
            {
                //取得房主 ID
                return clientRoom[0].GetUserID();
            }
            //不存在的ID   没有房主
            return -1;
        }

        //取得战绩
        public String GetRoomData()
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (Client client in clientRoom)
            {
                stringBuilder.Append(client.GetUserData() + "|");
            }
            //字符串是否大于 0
            if (stringBuilder.Length > 0)
            {
                stringBuilder.Remove(stringBuilder.Length - 1, 1);
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// 广播所有的客户端
        /// </summary>
        /// <param name="excludeClient"></param>
        public void BroadCastMessage(Client excludeClient, ActionCode actionCode, string data)
        {
            foreach (Client client in clientRoom)
            {
                if (client != excludeClient)
                {
                    //消息广播
                    server.SendResponse(client, actionCode, data);
                }
            }
        }

        //是否是房主
        public bool IsHouseOwner(Client client)
        {
            return client == clientRoom[0];
        }


        /// <summary>
        /// 关闭房间、客户端要推出
        /// </summary>
        /// <param name="client"></param>
        public void QuitRoom(Client client)
        {
            //如果是房主
            if (client == clientRoom[0])
            {
                Close();
            }
            else
            {
                //移除无需销毁
                clientRoom.Remove(client);
            }
            //移除自身
            //server.RemoveRoom(this);
        }

        /// <summary>
        /// 销毁房间
        /// </summary>
        public void Close()
        {
            foreach (Client client in clientRoom)
            {
                client.Room = null;
            }
            server.RemoveRoom(this);
        }


        /// <summary>
        /// 开始计时
        /// </summary>
        public void ShowTimer()
        {
            //使用线程
            new Thread(RunTimer).Start();
        }

        /// <summary>
        /// 使用线程计时
        /// </summary>
        private void RunTimer()
        {
            Thread.Sleep(1000);
            for (int i = 3; i > 0; i--)
            {
                //向所有的客户端广播消息
                BroadCastMessage(null, ActionCode.ShowTimer, i.ToString());
                //暂停1 毫秒
                Thread.Sleep(1000);
            }
            //3 秒之后开始游戏
            BroadCastMessage(null, ActionCode.StartPlay, "r");
        }
    }
}

using ServerFrameworkProject.Controller;
using ServerFrameworkProject.Tool;
using ShareProject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// 启动 TCP ,开启监听
/// </summary>
namespace ServerFrameworkProject.Servers
{
    class Server
    {
        private IPEndPoint iPEndPoint;
        private Socket serverSocket;
        private List<Client> clientList = new List<Client>();
        private ControllerManager controllerManager;
        //房间管理
        private List<Room> roomList = new List<Room>();

        public Server() { }

        public Server(string ipstr, int port)
        {
            controllerManager = new ControllerManager(this);
            SetIPAndPort(ipstr, port);
        }

        /// <summary>
        /// 设置 IP 以及 端口号
        /// </summary>
        /// <param name="ipstr"></param>
        /// <param name="port"></param>
        public void SetIPAndPort(string ipstr, int port)
        {
            this.iPEndPoint = new IPEndPoint(IPAddress.Parse(ipstr), port);
        }

        /// <summary>
        /// 启动监听
        /// </summary>
        public void Start()
        {
            //创建一个连接
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定IP
            serverSocket.Bind(iPEndPoint);
            //监听、队列长度为无限
            serverSocket.Listen(0);
            Console.WriteLine("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t服务器启动成功...");
            Console.WriteLine("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tIP\t:" + Helpr.AutoIP().ToString());
            Console.WriteLine("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPort\t:" + 6688);
            //异步接收
            serverSocket.BeginAccept(AcceptCallBack, null);
        }

        
        /// <summary>
        /// 处理连接回调
        /// </summary>
        /// <param name="ar"></param>
        private void AcceptCallBack(IAsyncResult ar)
        {
            //得到与客户端的连接
            Socket clientSocket = serverSocket.EndAccept(ar);
            //创建一个 client、将自身传递过去
            Client client = new Client(clientSocket, this);
            //启动client
            client.Start();
            //所有的客户端关联
            clientList.Add(client);
            //循环接收
            serverSocket.BeginAccept(AcceptCallBack, null);
        }

        /// <summary>
        /// 移除 Client的方法
        /// </summary>
        /// <param name="client"></param>
        public void RemoveClient(Client client)
        {
            //防止对象访问出现异常、多个客户端可能去访问
            lock (clientList)
            {
                Console.WriteLine("移除一个客户端" + client.ToString());
                //移除一个客户端
                clientList.Remove(client);
            }
        }
        
        /// <summary>
        /// 给客户端发出响应
        /// </summary>
        /// <param name="client"></param>
        /// <param name="actionCode"></param>
        /// <param name="data"></param>
        public void SendResponse(Client client, ActionCode actionCode, string data)
        {
            //给客户端响应
            client.Send(actionCode, data);
        }


        /// <summary>
        /// 处理消息
        /// </summary>
        /// <param name="requestCode"></param>
        /// <param name="actionCode"></param>
        /// <param name="data"></param>
        /// <param name="client"></param>
        public void HandleRequest(RequestCode requestCode, ActionCode actionCode, string data, Client client)
        {
            controllerManager.HandleRequest(requestCode, actionCode, data, client);
        }


        /// <summary>
        /// 创建房间
        /// </summary>
        /// <param name="client"></param>
        public void CreateRoom(Client client)
        {
            Room room = new Room(this);
            //创建房间
            room.AddClient(client);
            //管理房间
            roomList.Add(room);
        }

        /// <summary>
        /// 移除房间
        /// </summary>
        /// <param name="room"></param>
        public void RemoveRoom(Room room)
        {
            if (roomList != null && room != null)
            {
                roomList.Remove(room);
            }
        }

        /// <summary>
        /// 得到房间集合
        /// </summary>
        /// <returns></returns>
        public List<Room> GetRommList()
        {
            return roomList;
        }

        /// <summary>
        /// 根据 房间id 得到 id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Room GetRoomByID(int id)
        {
            foreach (Room room in roomList)
            {
                if (room.GetID() == id)
                {
                    return room;
                }
            }
            //找不到房间
            return null;
        }
    }
}

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

namespace ServerFrameworkProject.Tool
{
    class ConnHelper
    {
        /// <summary>
        /// 建立连接
        /// </summary>
        /// <returns></returns>
        public static MySqlConnection Connect()
        {
            MySqlConnection conn = new MySqlConnection(StringManager.CONNECTITONSTRING);
            try
            {
                //打开连接
                conn.Open();
                return conn;
            }
            catch (Exception e)
            {
                Console.WriteLine("连接数据库异常" + e);
                return null;
            }
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="mySqlConnection"></param>
        public static void CloseConnection(MySqlConnection mySqlConnection)
        {
            if (mySqlConnection != null)
            {
                mySqlConnection.Close();
            }
            else
            {
                Console.WriteLine(mySqlConnection + "不能为null");
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject.Tool
{
    class Helpr
    {
        /// <summary>
        /// 自动获取 IP
        /// </summary>
        public static string AutoIP()
        {
            string IP = string.Empty;
            foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
            {
                if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
                {
                    IP = _IPAddress.ToString();
                }
            }
            return IP;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 字符管理者
/// </summary>
namespace ServerFrameworkProject.Tool
{
    public static class StringManager
    {
        //SQL定义连接字符串connectionString
        public const string CONNECTITONSTRING = "Database=serverframepro;DataSource=localhost;port=3306;user id=root;password=123456";
    }
}

using ServerFrameworkProject.Servers;
using ServerFrameworkProject.Tool;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrameworkProject
{
    class Program
    {
        static void Main(string[] args)
        {
            //程序入口
            StartServer();
        }

        static void StartServer()
        {
            int Port = 6688;
            //获取本机IP地址
            Server server = new Server(Helpr.AutoIP().ToString(), Port);
            server.Start();
            Console.ReadLine();
        }

    }
}

2、数据库表结构设计
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值