zl程序教程

您现在的位置是:首页 >  前端

当前栏目

Unity 网络 之 Networking 实现简单的网络服务器和客户端通讯功能封装(可监听多个客户端)

封装服务器网络客户端 实现 简单 功能 多个
2023-09-11 14:20:50 时间

 

 

Unity 网络 之 Networking 实现简单的网络服务器和客户端通讯功能封装(可监听多个客户端)

 

目录

Unity 网络 之 Networking 实现简单的网络服务器和客户端通讯功能封装(可监听多个客户端)

一、简单介绍

二、实现原理

三、注意事项

四、效果预览

五、实现步骤

六、关键代码

七、参考工程


 

一、简单介绍

Unity 中网络通讯知识的整理。

本节介绍,在Unity中用 NetworkServer、NetworkClient 两个封装一个通用功能的类(包括建立连接,断开连接,发送不同类型数据,处理不同类型数据,注册处理数据的委托) 和 NetworkMessage (这里可以定义自己的消息类型,和重写消息数据结构)来解析数据信息,实现一个简单的网络通讯 demo。

因为是简单的封装,基本通讯可以满足使用,仅供参考,若有不对,请指出哈,谢谢。
 

二、实现原理

1、NetworkServer 构建相关服务器的封装类,例如 服务器监听 NetworkServer.Listen(),断开服务器所有连接NetworkServer.DisconnectAll(),关闭服务器NetworkServer.Shutdown(),服务器发送数据给所有客户端NetworkServer.SendToAll(),服务器取消注册事件 NetworkServer.UnregisterHandler(),服务器注册事件 NetworkServer.RegisterHandler()

2、NetworkClient 构建相关服务器的封装类,例如 客户端连接服务器 NetworkClient.Connect(),断开与服务器连接NetworkClient.Disconnect(),客户端发送数据给服务器NetworkClient.Send(),客户端取消注册事件 NetworkClient.UnregisterHandler(),客户端注册事件 NetworkClient.RegisterHandler()

3、继承 MessageBase 来定义自己的数据消息结构

 

三、注意事项

1、除了封装 NetworkServer、NetworkClient 两个类,还封装了一个统一管理 NetworkServer、NetworkClient  的管理类

NetManager 来实现来着的公有接口,外界只要调用 NetManager 的即可,内部会自动判断是否是构建服务器还是客户端

 

四、效果预览

 

五、实现步骤

1、打开Unity,新建工程

 

2、在场景中,搭建 UI,布局如下

 

3、新建几个脚本,完成 Networking 服务端、客户端的构建,以及 自定义数据类型事件,并有一个测试脚本,测试 Networking 的封装功能

 

4、把测试脚本和 NetManager 挂载到场景中个,并对应赋值

 

5、给 按钮添加测试脚本对应功能的接口函数

 

6、打包,运行多个客户端,即可完成数据通讯

 

六、关键代码

1、NetManager

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NetManager : MonoBehaviour
{

    private bool isServer = false;

    private NetServer server;
    private NetClient client;

    private string m_ip;
    private int m_port;

    Action addListenerEvent;

    /// <summary>
    /// 创建局域网通讯
    /// </summary>
    /// <param name="ip"></param>
    /// <param name="port"></param>
    public void SetUp(string ip, int port, Action action) {
        m_ip = ip;
        m_port = port;

        addListenerEvent = action;

        SetupClient();

    }

    /// <summary>
    /// 断开局域网通讯
    /// </summary>
    public void Shutdown(){
        if (server != null) {
            server.ShutdownServer();
        }

        if (client != null)
        {
            client.ShutdownClient();
        }
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="message"></param>
    public void SendUserMessage(string message) {
        if (server != null)
        {
            server.ServerSendUserMessage(message);
        }

        if (client != null)
        {
            client.ClientSendUserMessage(message);
        }
    }


    public void SetupEvent(Action<string> action) {
        if (action != null)
        {

            if (server != null)
            {
                server.SetupEvent += action;
            }

            if (client != null)
            {
                Debug.Log(" client.SetupEvent += action; ");
                client.SetupEvent += action;
            }

        }
    }

    public void ShutdownEvent(Action<string> action)
    {
        if (action != null)
        {

            if (server != null)
            {
                server.ShutdownEvent += action;
            }

            if (client != null)
            {
                client.ShutdownEvent += action;
            }

        }
    }

    public void OneTerminalConnectedEvent(Action<string> action)
    {
        if (action != null)
        {

            if (server != null)
            {
                server.OneTerminalConnectedEvent += action;
            }

            if (client != null)
            {
                client.OneTerminalConnectedEvent += action;
            }

        }
    }

    public void OneTerminalDisconnectedEvent(Action<string> action)
    {
        if (action != null)
        {

            if (server != null)
            {
                server.OneTerminalDisconnectedEvent += action;
            }

            if (client != null)
            {
                client.OneTerminalDisconnectedEvent += action;
            }

        }
    }

    public void NetErrorEvent(Action<string> action)
    {
        if (action != null)
        {

            if (server != null)
            {
                server.NetErrorEvent += action;
            }

            if (client != null)
            {
                client.NetErrorEvent += action;
            }

        }
    }

    public void RecieiveUserMessageHandlerEvent(Action<string> action)
    {
        if (action != null)
        {

            if (server != null)
            {
                server.RecieiveUserMessageHandlerEvent += action;
            }

            if (client != null)
            {
                client.RecieiveUserMessageHandlerEvent += action;
            }

        }
    }



    #region  私有方法处理

    void SetupClient()
    {
        if (client == null)
        {
            client = new NetClient(m_ip, m_port);
    
        }

        if (addListenerEvent != null)
        {
            addListenerEvent();
        }
        else {
            Debug.Log("addListenerEvent is null");
        }


        client.SetupClient();

        

        // 后期看是否可以改为 InvokeRepeating() 几次后,没有再去创建服务
        Invoke("ToSetupServer", 1.0f);

    }

    void ToSetupServer()
    {
        // 没有连接服务器,创建服务器
        if (client.GetClientConnectState() == false)
        {
            // 先处理Client,断开处理
            client.Disconnect();
            client = null;

            SetupServer();
        }

    }


    void SetupServer()
    {
        if (server == null)
        {
            server = new NetServer(m_port);

            if (addListenerEvent != null)
            {
                addListenerEvent();
            }
        }

        // 为服务端
        isServer = true;

        server.SetupServer();
    }

    /// <summary>
    /// 监听客户端是否连接服务器
    /// </summary>
    /// <returns></returns>
    IEnumerator ClientConnectListener() {
        while (client.GetClientConnectState()==false)
        {
            yield return new WaitForSeconds(1.0f);
        }
    }

    #endregion


}

 

2、NetServer

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class NetServer 
{


    public Action<string> SetupEvent;
    public Action<string> ShutdownEvent;
    public Action<string> OneTerminalConnectedEvent;
    public Action<string> OneTerminalDisconnectedEvent;
    public Action<string> NetErrorEvent;
    public Action<string> RecieiveUserMessageHandlerEvent;

    int m_port;

    public NetServer(int port) {
        m_port = port;
    }


    /// <summary>
    /// 建立服务器
    /// </summary>
    public void SetupServer()
    {
        if (!NetworkServer.active)
        {
            Debug.Log("setup server");
            ServerRegisterHandler();
            NetworkServer.Listen(m_port);

            if (NetworkServer.active)
            {
                Debug.Log("Server setup ok.");
                if (SetupEvent != null) {
                    SetupEvent("Server setup ok.");
                }
            }
        }
    }

    /// <summary>
    /// 停止服务器端
    /// </summary>
    public void ShutdownServer()
    {
        if (NetworkServer.active)
        {
            ServerUnregisterHandler();
            NetworkServer.DisconnectAll();
            NetworkServer.Shutdown();

            if (!NetworkServer.active)
            {
                Debug.Log("shut down server");
                if (ShutdownEvent != null)
                {
                    ShutdownEvent("shut down server");
                }

            }
        }
    }


    /// <summary>
    /// 服务器端向所有客户端发送信息
    /// </summary>
    public void ServerSendUserMessage(string message)
    {
        if (NetworkServer.active)
        {
            UserMessage um = new UserMessage();
            um.message = message;
            if (NetworkServer.SendToAll(MyMsgType.UserMessage, um))
            {
                Debug.Log("Server send:" + message);

               
            }
        }
    }



    /// <summary>
    /// 服务器端注册事件
    /// </summary>
    private void ServerRegisterHandler()
    {
        NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnected);
        NetworkServer.RegisterHandler(MsgType.Disconnect, OnServerDisconnected);
        NetworkServer.RegisterHandler(MsgType.Error, OnServerError);
        NetworkServer.RegisterHandler(MyMsgType.UserMessage, ServerRecieiveUserMessageHandler);

    }


    /// <summary>
    /// 服务器端注销事件
    /// </summary>
    private void ServerUnregisterHandler()
    {
        NetworkServer.UnregisterHandler(MsgType.Connect);
        NetworkServer.UnregisterHandler(MsgType.Disconnect);
        NetworkServer.UnregisterHandler(MsgType.Error);
        NetworkServer.UnregisterHandler(MyMsgType.UserMessage);
        
    }


    /// <summary>
    /// 服务器端有客户端连入事件
    /// </summary>
    /// <param name="netMsg">Net message.</param>
    private void OnServerConnected(NetworkMessage netMsg)
    {
        Debug.Log("One client connected to server");

        if (OneTerminalConnectedEvent != null)
        {
            OneTerminalConnectedEvent("One client connected to server");
        }
    }

    /// <summary>
    /// 服务器端有客户端断开事件
    /// </summary>
    /// <param name="netMsg">Net message.</param>
    private void OnServerDisconnected(NetworkMessage netMsg)
    {
        Debug.Log("One client connected from server");

        if (OneTerminalDisconnectedEvent != null)
        {
            OneTerminalDisconnectedEvent("One client Disconnected from server");
        }
    }

    /// <summary>
    /// 服务器端错误事件
    /// </summary>
    /// <param name="netMsg">Net message.</param>
    private void OnServerError(NetworkMessage netMsg)
    {
        ServerUnregisterHandler();
        Debug.Log("Server error");

        if (NetErrorEvent != null)
        {
            NetErrorEvent("Server error");
        }
    }

    /// <summary>
    /// 消息处理
    /// </summary>
    /// <param name="netMsg"></param>
    private void ServerRecieiveUserMessageHandler(NetworkMessage netMsg)
    {
        UserMessage Msg = netMsg.ReadMessage<UserMessage>();
        Debug.Log("Server get:" + Msg.message);

        // 这里服务器作为中转站转发信息
        ServerSendUserMessage(Msg.message);

        if (RecieiveUserMessageHandlerEvent != null)
        {
            RecieiveUserMessageHandlerEvent("Server get:" + Msg.message);
        }
    }
}

 

3、NetClient

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class NetClient
{

    public Action<string> SetupEvent;
    public Action<string> ShutdownEvent;
    public Action<string> OneTerminalConnectedEvent;
    public Action<string> OneTerminalDisconnectedEvent;
    public Action<string> NetErrorEvent;
    public Action<string> RecieiveUserMessageHandlerEvent;

    /// <summary>
    /// 网络客户端
    /// </summary>
    private NetworkClient myClient;

    private string m_ip;

    private int m_port;

    public NetClient(string ip, int port) {
        myClient = new NetworkClient();

        m_ip = ip;
        m_port = port;

    }

    /// <summary>
    /// 建立客户端
    /// </summary>
    public void SetupClient()
    {
        Debug.Log("onclick setup client");

        if (!myClient.isConnected)
        {
            Debug.Log("setup client");
            ClientRegisterHandler();
            myClient.Connect(m_ip, m_port);

            if (SetupEvent != null)
            {
                SetupEvent("client setup ok.");
            }
        }
    }

    /// <summary>
	/// 停止客户端
	/// </summary>
	public void ShutdownClient()
    {
        if (myClient.isConnected)
        {
            Disconnect();

            if (ShutdownEvent != null)
            {
                ShutdownEvent("client Disconnect.");
            }
        }
    }

    /// <summary>
    /// 断开的处理
    /// </summary>
    internal void Disconnect() {
        ClientUnregisterHandler();
        myClient.Disconnect();

        //NetworkClient.Shutdown()使用后,无法再次连接。
        //This should be done when a client is no longer going to be used.
        //myClient.Shutdown ();
    }

    /// <summary>
    /// 获取客户端连接状态
    /// </summary>
    /// <returns></returns>
    public bool GetClientConnectState() {
        return myClient.isConnected;
    }


    /// <summary>
	/// 客户端向服务器端发送信息
	/// </summary>
	public void ClientSendUserMessage(string message)
    {
        if (myClient.isConnected)
        {
            UserMessage um = new UserMessage();
            um.message = message;
            if (myClient.Send(MyMsgType.UserMessage, um))
            {
                Debug.Log("Client send:" + message);
            }
        }
    }



    /// <summary>
    /// 客户端注册事件
    /// </summary>
    private void ClientRegisterHandler()
    {
        myClient.RegisterHandler(MsgType.Connect, OnClientConnected);
        myClient.RegisterHandler(MsgType.Disconnect, OnClientDisconnected);
        myClient.RegisterHandler(MsgType.Error, OnClientError);
        myClient.RegisterHandler(MsgType.NotReady, OnClientNotReady);
        myClient.RegisterHandler(MyMsgType.UserMessage, ClientRecieiveUserMessageHandler);
        
    }

    /// <summary>
    /// 客户端注销事件
    /// </summary>
    private void ClientUnregisterHandler()
    {
        myClient.UnregisterHandler(MsgType.Connect);
        myClient.UnregisterHandler(MsgType.Disconnect);
        myClient.UnregisterHandler(MsgType.Error);
        myClient.UnregisterHandler(MsgType.NotReady);
        myClient.UnregisterHandler(MyMsgType.UserMessage);
  
    }


    /// <summary>
	/// 客户端连接到服务器事件
	/// </summary>
	/// <param name="netMsg">Net message.</param>
	private void OnClientConnected(NetworkMessage netMsg)
    {
        Debug.Log("Client connected to server");

        if (OneTerminalConnectedEvent != null)
        {
            OneTerminalConnectedEvent("Client connected to server");
        }
    }

    /// <summary>
    ///客户端从服务器断开事件
    /// </summary>
    /// <param name="netMsg">Net message.</param>
    private void OnClientDisconnected(NetworkMessage netMsg)
    {
        Debug.Log("Client disconnected from server");

        if (OneTerminalDisconnectedEvent != null)
        {
            OneTerminalDisconnectedEvent("Client disconnected from server");
        }
    }

    /// <summary>
    /// 客户端错误事件
    /// </summary>
    /// <param name="netMsg">Net message.</param>
    private void OnClientError(NetworkMessage netMsg)
    {
        ClientUnregisterHandler();
        Debug.Log("Client error");

        if (NetErrorEvent != null)
        {
            NetErrorEvent("Client error");
        }
    }

    private void OnClientNotReady(NetworkMessage netMsg)
    {
        ClientUnregisterHandler();
        Debug.Log("Client not Ready");

        
    }

    /// <summary>
	/// 客户端接收到服务器端信息事件
	/// </summary>
	/// <param name="netMsg">Net message.</param>
	private void ClientRecieiveUserMessageHandler(NetworkMessage netMsg)
    {
        UserMessage Msg = netMsg.ReadMessage<UserMessage>();
        Debug.Log("Client get:" + Msg.message);

        if (RecieiveUserMessageHandlerEvent != null)
        {
            RecieiveUserMessageHandlerEvent("Client get:" + Msg.message);
        }
    }

}


        

 

4、MyMsgType

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 自定义的消息码,别与 MsgType 重复码
/// </summary>
public class MyMsgType 
{
    public const short UserMessage = 64;
}

 

5、UserMessage

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

/// <summary>
/// 自定义信息类
/// </summary>
public class UserMessage : MessageBase
{
    // 信息
    public string message;
}

 

6、Test_NetManager

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(NetManager))]
public class Test_NetManager : MonoBehaviour
{

    /// <summary>
    /// 服务器ip地址
    /// </summary>
    public InputField ip;
    /// <summary>
    /// 服务器端口
    /// </summary>
    public InputField port;
    /// <summary>
    /// 要发送的信息
    /// </summary>
    public InputField send;

    public Text LogMessahe_Text;

    private NetManager netManager;

    // Start is called before the first frame update
    void Start()
    {
        netManager = GetComponent<NetManager>();
        LogMessahe_Text.text = "Start...";
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }


    void AddListener() {

        SetupEvent();
        ShutdownEvent();
        OneTerminalConnectedEvent();
        OneTerminalDisconnectedEvent();
        NetErrorEvent();

        RecieiveUserMessageHandlerEvent();
    }


    public void ConnectNet() {
        if (netManager != null) {
            if (string.IsNullOrEmpty(ip.text) || string.IsNullOrEmpty(port.text)) {

                Debug.Log(" Ip 或者 port 不能为空");

                return;
            }

            netManager.SetUp(ip.text, int.Parse(port.text),()=> {
                // 连接之后进行事件监听添加
                AddListener();
            });

            
        }
    }

    public void SendMessage() {
        if (netManager != null)
        {
            if (string.IsNullOrEmpty(send.text) )
            {
                Debug.Log(" send 不能为空");

                return;
            }

            netManager.SendUserMessage(send.text);

            LogMessahe_Text.text += "\r\n" + send.text;
        }
    }

    public void DisconnectNet() {
        if (netManager != null) {
            netManager.Shutdown();
        }
    }





    public void SetupEvent()
    {
        Debug.Log("SetupEvent");
        netManager.SetupEvent((str)=> {

            LogMessahe_Text.text +="\r\n" + str;
        });
    }

    public void ShutdownEvent()
    {
        netManager.ShutdownEvent((str) =>
        {

            LogMessahe_Text.text += "\r\n" + str;
        });
    }

    public void OneTerminalConnectedEvent()
    {
        netManager.OneTerminalConnectedEvent((str) =>
        {

            LogMessahe_Text.text += "\r\n" + str;
        });
    }

    public void OneTerminalDisconnectedEvent()
    {
        netManager.OneTerminalDisconnectedEvent((str) =>
        {

            LogMessahe_Text.text += "\r\n" + str;
        });
    }

    public void NetErrorEvent()
    {
        netManager.NetErrorEvent((str) =>
        {

            LogMessahe_Text.text += "\r\n" + str;
        });
    }

    public void RecieiveUserMessageHandlerEvent()
    {
        netManager.RecieiveUserMessageHandlerEvent((str) =>
        {

            LogMessahe_Text.text += "\r\n" + str;
        });
    }


}

 

七、参考工程

工程下载地址:https://download.csdn.net/download/u014361280/12471621