Unity中与WebSocket服务端建立长连接

笔记记录,由于项目需求需要和用WebSocket编写的服务端建立长连接进行实时同步,因此封装的一个脚本,这边用到了BaseHTTP的插件,因此使用这个脚本时需要导入BaseHTTP插件。脚本可以直接拿来用,可以直接通过类名点出单例来使用,接收消息的回调都通过Action事件返回,BaseHTTP插件可以自行查找下载,我也会专门写一篇专栏为了码友们提供学习参考用的一些插件的购买和下载,需要注意的本人提供的仅供学习参考用,如果版权问题概不负责,代码如下:

using System;
using System.IO;
using BestHTTP;
using BestHTTP.WebSocket;
using BestHTTP.WebSocket.Frames;
using UnityEngine;

public class WebSocketClient
{
    private WebSocket m_WebSocket=null;

    private bool m_IsInit = false;

    public string Url = "ws://127.0.0.1:6000";

    public Action<WebSocket> OnAction_Opened = null;
    public Action<WebSocket, UInt16,string> OnAction_Closed = null;
    public Action<WebSocket,string> OnAction_Error = null;
    public Action<WebSocket, string> OnAction_MessageReceived = null;
    public Action<WebSocket, byte[]> OnAction_Binary=null;
    public Action<WebSocket, WebSocketFrameReader> OnAction_IncompleteFrame = null;

    public bool IsConnected
    {
        get { return m_WebSocket!=null&&m_WebSocket.IsOpen; }
    }

    public HTTPRequest HttpRequest
    {
        get { return m_WebSocket!=null ? m_WebSocket.InternalRequest : null; }
    }

    #region 单例
    static protected WebSocketClient _instance;
    static protected bool IsCreate = false;

    public static WebSocketClient Instance
    {
        get
        {
            if (IsCreate == false)
            {
                CreateInstance();
            }

            return _instance;
        }
    }

    public static void CreateInstance()
    {
        if (IsCreate == true)
            return;

        IsCreate = true;
        _instance = new WebSocketClient();
    }

    public static void ReleaseInstance()
    {
        _instance = default(WebSocketClient);
        IsCreate = false;
    }
    #endregion

    #region 构造函数
    private WebSocketClient()
    {

    }
    #endregion

    #region 初始化
    /// <summary>
    /// 初始化
    /// </summary>
    public bool Init(string url)
    {
        if (!m_IsInit)
        {
            m_IsInit = true;

            m_WebSocket = new WebSocket(new System.Uri(url));
            m_WebSocket.OnOpen += OnOpen;
            m_WebSocket.OnMessage += OnMessageReceived;
            m_WebSocket.OnError += OnError;
            m_WebSocket.OnClosed += OnClosed;
            m_WebSocket.OnBinary += Onbinary;
            m_WebSocket.OnIncompleteFrame += OnIncompleteFrame;

            Debug.Log("初始化WebSocket成功,URL:" + url);

            return true;
        }
        Debug.LogWarning("初始化WebSocket失败,URL:" + url);
        return false;
    }
    public bool Init(string url, string origin, string protocol)
    {
        if (!m_IsInit)
        {
            m_IsInit = true;

            m_WebSocket = new WebSocket(new System.Uri(url), origin, protocol);
            m_WebSocket.OnOpen += OnOpen;
            m_WebSocket.OnMessage += OnMessageReceived;
            m_WebSocket.OnError += OnError;
            m_WebSocket.OnClosed += OnClosed;
            m_WebSocket.OnBinary += Onbinary;
            m_WebSocket.OnIncompleteFrame += OnIncompleteFrame;

            Debug.Log("初始化WebSocket成功,URL:" + url);

            return true;
        }
        Debug.LogWarning("初始化WebSocket失败,URL:" + url);
        return false;
    }

    public bool Init(Uri url)
    {
        if (!m_IsInit)
        {
            m_IsInit = true;

            m_WebSocket = new WebSocket(url);
            m_WebSocket.OnOpen += OnOpen;
            m_WebSocket.OnMessage += OnMessageReceived;
            m_WebSocket.OnError += OnError;
            m_WebSocket.OnClosed += OnClosed;
            m_WebSocket.OnBinary += Onbinary;
            m_WebSocket.OnIncompleteFrame += OnIncompleteFrame;

            Debug.Log("初始化WebSocket成功,URL:" + url);

            return true;
        }
        Debug.LogWarning("初始化WebSocket失败,URL:" + url);
        return false;
    }

    public bool Init(Uri url, string origin, string protocol)
    {
        if (!m_IsInit)
        {
            m_IsInit = true;

            m_WebSocket = new WebSocket(url, origin, protocol);
            m_WebSocket.OnOpen += OnOpen;
            m_WebSocket.OnMessage += OnMessageReceived;
            m_WebSocket.OnError += OnError;
            m_WebSocket.OnClosed += OnClosed;
            m_WebSocket.OnBinary += Onbinary;
            m_WebSocket.OnIncompleteFrame += OnIncompleteFrame;

            Debug.Log("初始化WebSocket成功,URL:" + url);

            return true;
        }
        Debug.LogWarning("初始化WebSocket失败,URL:" + url);
        return false;
    }

    /// <summary>
    /// 重新初始化
    /// </summary>
    public bool ReInit(string url)
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Close();

            m_WebSocket.OnOpen = null;
            m_WebSocket.OnMessage = null;
            m_WebSocket.OnError = null;
            m_WebSocket.OnClosed = null;
            m_WebSocket.OnBinary = null;
            m_WebSocket.OnIncompleteFrame = null;

            m_WebSocket = null;

            m_IsInit = false;

            Debug.Log("关闭重置WebSocket成功");
        }

        return Init(url);
    }
    public bool ReInit(string url, string origin, string protocol)
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Close();

            m_WebSocket.OnOpen = null;
            m_WebSocket.OnMessage = null;
            m_WebSocket.OnError = null;
            m_WebSocket.OnClosed = null;
            m_WebSocket.OnBinary = null;
            m_WebSocket.OnIncompleteFrame = null;

            m_WebSocket = null;

            m_IsInit = false;

            Debug.Log("关闭重置WebSocket成功");
        }

        return Init(url, origin, protocol);
    }
    public bool ReInit(Uri url)
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Close();

            m_WebSocket.OnOpen = null;
            m_WebSocket.OnMessage = null;
            m_WebSocket.OnError = null;
            m_WebSocket.OnClosed = null;
            m_WebSocket.OnBinary = null;
            m_WebSocket.OnIncompleteFrame = null;

            m_WebSocket = null;

            m_IsInit = false;

            Debug.Log("关闭重置WebSocket成功");
        }

        return Init(url);
    }
    public bool ReInit(Uri url, string origin, string protocol)
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Close();

            m_WebSocket.OnOpen = null;
            m_WebSocket.OnMessage = null;
            m_WebSocket.OnError = null;
            m_WebSocket.OnClosed = null;
            m_WebSocket.OnBinary = null;
            m_WebSocket.OnIncompleteFrame = null;

            m_WebSocket = null;

            m_IsInit = false;

            Debug.Log("关闭重置WebSocket成功");
        }

        return Init(url, origin, protocol);
    }
    #endregion

    #region 连接服务
    /// <summary>
    /// 主动连接
    /// </summary>
    /// <param name="url">连接地址</param>
    /// <returns></returns>
    public bool Connect(string url)
    {
        if (ReInit(url))
        {
            m_WebSocket.Open();
            Debug.Log("打开WebSocket");

            return m_WebSocket.IsOpen;
        }
        else
        {
            return false;
        }
    }
    public bool Connect(string url, string origin, string protocol)
    {
        if (ReInit(url, origin, protocol))
        {
            m_WebSocket.Open();
            Debug.Log("打开WebSocket");

            return m_WebSocket.IsOpen;
        }
        else
        {
            return false;
        }
    }
    public bool Connect(Uri url)
    {
        if (ReInit(url))
        {
            m_WebSocket.Open();
            Debug.Log("打开WebSocket");

            return m_WebSocket.IsOpen;
        }
        else
        {
            return false;
        }
    }
    public bool Connect(Uri url, string origin, string protocol)
    {
        if (ReInit(url, origin, protocol))
        {
            m_WebSocket.Open();
            Debug.Log("打开WebSocket");

            return m_WebSocket.IsOpen;
        }
        else
        {
            return false;
        }
    }

    public bool Connect()
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Open();
            Debug.Log("打开WebSocket");

            return m_WebSocket.IsOpen;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 断开连接
    /// </summary>
    /// <returns></returns>
    public bool DisConnect()
    {
        if (m_WebSocket != null)
        {
            m_WebSocket.Close();
            return true;
        }
        return false;
    }
    #endregion

    #region 发送消息
    public void SendMessage(int msgType, byte[] data)
    {
        //内存流对象
        using (MemoryStream ms = new MemoryStream())
        {
            using (BinaryWriter bw = new BinaryWriter(ms))
            {
                //先写入长度
                bw.Write(msgType);
                //再写入数据
                bw.Write(data);

                byte[] byteArray = new byte[(int)ms.Length];
                Buffer.BlockCopy(ms.GetBuffer(), 0, byteArray, 0, (int)ms.Length);

                m_WebSocket?.Send(byteArray);
            }
        }
    }

    public void SendMessage(byte[] data)
    {
        m_WebSocket?.Send(data);
    }

    public void SendMessage(string data)
    {
        m_WebSocket?.Send(data);
        Debug.Log(string.Format("{0:D2}:{1:D2}:{2:D2}", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second) + data);
    }
    #endregion

    #region 回调
    /// <summary>
    /// 连接成功回调
    /// </summary>
    /// <param name="webSocket"></param>
    private void OnOpen(WebSocket webSocket)
    {
        Debug.Log("连接成功!");
        OnAction_Opened?.Invoke(webSocket);
    }

    /// <summary>
    /// 关闭连接回调
    /// </summary>
    /// <param name="webSocket"></param>
    private void OnClosed(WebSocket webSocket, UInt16 code, string message)
    {
        Debug.Log("关闭连接:"+ message);
        OnAction_Closed?.Invoke(webSocket,code,message);
    }

    /// <summary>
    /// 错误回调
    /// </summary>
    /// <param name="webSocket"></param>
    /// <param name="reason"></param>
    private void OnError(WebSocket webSocket,string reason)
    {
        Debug.LogError($"错误消息:{reason}");
        OnAction_Error?.Invoke(webSocket,reason);
    }

    /// <summary>
    /// 收到消息
    /// </summary>
    /// <param name="webSocket"></param>
    /// <param name="message"></param>
    private void OnMessageReceived(WebSocket webSocket, string message)
    {
        Debug.Log($"接收到消息:{message}");
        OnAction_MessageReceived?.Invoke(webSocket, message);
    }

    /// <summary>
    /// 收到不完整帧时的消息
    /// </summary>
    /// <param name="webSocket"></param>
    /// <param name="frame"></param>
    private void OnIncompleteFrame(WebSocket webSocket, WebSocketFrameReader frame)
    {

        Debug.LogWarning("接收到不完整帧的消息:" + frame.DataAsText);
        OnAction_IncompleteFrame?.Invoke(webSocket,frame);
    }

    /// <summary>
    /// 接收二进制消息
    /// </summary>
    /// <param name="webSocket"></param>
    /// <param name="data"></param>
    private void Onbinary(WebSocket webSocket, byte[] data)
    {
        Debug.Log("接收到二进制消息");
        OnAction_Binary?.Invoke(webSocket,data);
    }
    #endregion
}

使用的测试脚本如下,测试脚本中连接时如果要添加token等可以按脚本中编写,如果不需要就直接删除AddHeader的代码即可:

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

public class WebSocketTest : MonoBehaviour
{
    public string URL = "ws://127.0.0.1:6000";

    public string Content = "测试内容";

    // Start is called before the first frame update
    void Start()
    {
        WebSocketClient.Instance.Init(URL);
        WebSocketClient.Instance.HttpRequest.AddHeader("X-AUTH-TOKEN", "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJkNTU0Njg3Zi1jNGZkLTQ0MjQtOGJlOS1lMzEzMWU0Yzk4MDYiLCJzdWIiOiJUSi1ZTCIsImlhdCI6MTY1MzM1NjQ1N30.jE7h6z50etjpEXrC86VXgs3GXnr1y5l7GkV-FiPvaZ4");
        //WebSocketClient.Instance.HttpRequest.AddHeader("Content-Type", "application/json");
        WebSocketClient.Instance.Connect();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            WebSocketClient.Instance.SendMessage(Content);
        }
        if (Input.GetKeyDown(KeyCode.Q))
        {
            WebSocketClient.Instance.DisConnect();
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            WebSocketClient.Instance.Connect(URL);
        }
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TenderRain。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值