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

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

时间:2023-02-05 21:03:07浏览次数:66  
标签:return string C# System Server client Sokcet using public

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

1、客户端和服务器共享工程

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

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

接下来就是我们的服务器核心的代码:如果下图所示,依次共享源码:

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

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、数据库表结构设计

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


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


标签:return,string,C#,System,Server,client,Sokcet,using,public
From: https://blog.51cto.com/u_15163225/6038427

相关文章

  • Docker数据管理
    一、docker数据管理管理Docker容器中数据主要有两种方式:数据卷(DataVolumes)和数据卷容器(DataVolumesContainers)。1、数据卷数据卷是一个供容器使用的特殊目录,位于容器......
  • 中缀/后缀/前缀表达式及相互转换的手算详细步骤及C代码实现
    文章目录​​1三种算术表达式​​​​2后缀表达式相关考点​​​​2.1中缀表达式转后缀表达式​​​​2.1.1手算​​​​2.1.2机算​​​​2.2后缀表达式求值​​​​......
  • 【JavaScript】3_深挖数据类型
    4、其他的数据类型布尔值(Boolean)-布尔值主要用来进行逻辑判断-布尔值只有两个true和false-使用typeof检查......
  • Linux-curl下载报错解决方法
    报错提示:curl:(92)HTTP/2stream1wasnotclosedcleanlybeforeendoftheunderlyingstream==>ERROR:Failurewhiledownloadinghttps://github.com/Jguer/ya......
  • windows处理C盘空间不够
    现象:c盘东西太多,即将满载处理:通过everything查找发现大于50M的文件有size:>50mbc:一、处理pagefile.sysPagefile.sys作为Windows10系统中虚拟内存的临时页面文......
  • Day2——初识C,那些点滴事件
    #include<stdio.h>//包含头文件#defineP11//宏定义intmain()//执行操作入口{printf("haha\n");......
  • NFS磁盘共享(centos)
    背景:由于生产服务器数据磁盘空间即将满载,找了台磁盘空闲的服务器通过nfs的方式把磁盘共享给生产服务器,用于备份数据或者迁移数据使用。环境:文件服务端:xxx.xxx.xxx.38客......
  • Respecting causality is all you need for training physics-informed neural networ
      未发表本篇工作时关于连续时间的PDE。也是从因果关系的角度入手,最近看过几篇该作者的工作。(简而言之就是从初始条件方向开始训练)目前的PINN框架缺乏尊重物理系统演......
  • Accessing proc File System
    youaregoingtotakealookatanothersystemdirectorycalled/proc.The/procdirectoryisalsoknownasprocfs,anditcontainsusefulinformationaboutp......
  • Docker容器资源扩容操作
    Docker容器资源扩容通过Docker部署的容器服务在运行了一段时间后,发现容器部署的服务资源不足,这时需要对容器服务的资源进行扩容;扩容命令操作dockerupdate[OPTIONS]CO......