前言:
此项目基于unity,使用c#语言构建一个通用的简单的客户端框架,比较简陋但是易懂。
在第一版的基础上,我更详细的描述了模块的编写过程逻辑。
学习目标:学习构建一个游戏客户端基本的网络模块
网络模块的设计实现:
1.网络管理者NetManager类
该类将有关网络通讯部分的功能封装,实现网络模块的主要功能。
主要利用观察者模式,让框架拥有松耦合,灵活性,可拓展性的特性。
整合了客户端连接服务器Connect,关闭与服务器的连接Close,想服务器发送消息Send等基本网络通讯功能。
网络通讯可以抽象为如下阶段
连接Connect -> 发送Send -> 接收Receive -> 客户端处理消息 -> 发送/接收/处理循环->关闭Close
下面是具体实现
关键属性
Socket:连接套接字
readBuff:接受消息的缓冲区
writeQueue:发送消息的写入队列
isClosing :记录是否连接
private static Socket socket;
//接收缓存区
private static ByteArray readBuff;
//写入队列
private static Queue<ByteArray> writeQueue;
private static bool isClosing = false;
这些属性是NetManager的基本字段,十分重要。是实现网络通讯的基础。
网络事件处理
为了更好的可扩展性,
我们使用观察者模式,也就是采用事件驱动模式。
在这种模式中,存在一个发布者(Subject)和多个订阅者(Observers),订阅者会注册(监听)某些事件,当事件发生时,所有订阅该事件的订阅者都会被通知并触发相应的处理逻辑。
这样可以在实现具体方法的时候,方便的触发各种方法。
下面是实现观察者模式的逻辑
网络事件枚举类型
首先利用一个枚举类型NetEvent,存储常用的网络事件名称,该类型作为监听器的key值,用来触发对应事件,方便后续调用。
(其实当然也可以用其他类型,来定义监听器的key值,比如直接用string注册,但是不方便调用,可能会出错)
public enum NetEvent
{
ConnectSucc = 1,
ConnectFail = 2,
Close = 3,
}
实现观察者模式/事件驱动核心部分
1.定义委托
类型名EventListener(参数为string)。
作为监听者的模板,在事件触发的时候,监听该事件的监听者被会触发。
2.定义一个事件列表,
为字典类型<NetEvent,EventListener>
用于记录每种网络事件对应的回调方法。存储了不同网络事件及其对应事件的监听者。
3.实现 添加事件监听者 与 删除事件监听者 的方法。
其中的if/else逻辑是:
如果这个事件不存在就创建一个事件,并为其添加监听者。如果已经存在,就在原事件上再添加监听者。
4.实现 事件触发方法。
方法需要一个网络事件类型,和一个字符串(用于作为被触发的监听器的参数)
具体源代码:
#region 事件处理
//事件委托类型
public delegate void EventListener(string err);
//事件监听列表
private static Dictionary<NetEvent, EventListener>
eventListeners = new Dictionary<NetEvent,EventListener>();
//添加事件监听
public static void AddEventListener(NetEvent netEvent, EventListener listener)
{
if (eventListeners.ContainsKey(netEvent))
{
eventListeners[netEvent] += listener;
}
else
{
eventListeners[netEvent] = listener;
}
}
//删除事件监听
public static void RemoveEventListenner(NetEvent netEvent, EventListener listener)
{
if (eventListeners.ContainsKey(netEvent))
{
eventListeners[netEvent] -= listener;
}
else
{
eventListeners.Remove(netEvent);
}
}
#endregion
//分发(触发)事件
public static void FireEvent(NetEvent netEvent, string err)
{
if (eventListeners.ContainsKey(netEvent))
{
eventListeners[netEvent](err);
}
else
{
throw new Exception("不存在此事件");
}
}
具体基本网络通讯功能的实现(向服务器发送请求)
使用套接字进行端对端连接
其中观察者在其中用于触发连接成功与失败的提示
1.Connet
功能要求:根据ip和端口,向服务器发起连接。
实现逻辑,