由于项目需要,公司的后端迟迟无法就位,自己便利用 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、数据库表结构设计