Unity 網絡 之 Networking 實現簡單的網絡服務器和客戶端通訊功能封裝(可監聽多個客戶端)

 

 

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章