[学习笔记][Unity3D网络游戏实战]客户端基本网络框架(重制版)

前言:

此项目基于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和端口,向服务器发起连接。

实现逻辑,