unity websockt断线重连和心跳检测

本篇文章是基于BestHttp插件实现的websocket,大家可以搜索这个插件进行学习使用。

websocket是为了克服http无法双向通信而引入的,在通常的使用中,可以复用http的端口与功能,除此外,他们没有其他的联系,而是完全是独立的协议,通常情况下,http是单向的web 服务,而websocket是全双工的,服务器和客户端可以实时的传输信息,在引用时他们可以在http服务器上同时部署。

在弱网环境下,发送消息无法抵达接收端;抑或,断网到浏览器约定时限等一些异常情况都会触发onclose和onerror,所以理论上,我们只要在onclose和onerror时,重新创建长连接就可以。

思路

弱网、断连所导致重连都是被动的,而在一般的websocket连接中都是存在心跳机制的,客户端和服务端约定一个特定的心跳消息用于检测链路是否通信正常
我们通过心跳机制,在客户端来检测链路的正常,在约定时间间隔内收不到心跳或者其他任何通信消息时,客户端进行主动重连。当连接成功时,开启心跳;在收到消息时,重置心跳并开启下一轮检测,所以我们只需要在onopen和onmessage中加入心跳检测就行。

code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BestHTTP;
using BestHTTP.WebSocket;
using BestHTTP.Examples;
using System;

public class WebSocketModel : MonoBehaviour
{
    string address;
    WebSocket webSocket;
    private bool lockReconnect = false;
    private Coroutine _pingCor,_clientPing,_serverPing;

    private void Start()
    {
        CreateWebSocket();
    }

    void CreateWebSocket()
    {
        try
        {
            webSocket = new WebSocket(new System.Uri("ws://8888ws"));//websocket访问地址
            InitHandle();
            webSocket.Open();
        }
        catch(Exception e)
        {
            Debug.Log("websocket连接异常:" + e.Message);
            ReConnect();
        }
       
    }

    void InitHandle()
    {
        RemoveHandle();
        webSocket.OnOpen += OnOpen;
        webSocket.OnMessage += OnMessageReceived;
        webSocket.OnClosed += OnClosed;
        webSocket.OnError += OnError;
    }

    void RemoveHandle()
    {
        webSocket.OnOpen -= OnOpen;
        webSocket.OnMessage -= OnMessageReceived;
        webSocket.OnClosed -= OnClosed;
        webSocket.OnError -= OnError;
    }

    void OnOpen(WebSocket ws)
    {
        Debug.Log("websocket连接成功");
        if(_pingCor!=null)
        {
            StopCoroutine(_pingCor);
            _pingCor = null;
        }
        _pingCor = StartCoroutine(HeartPing());
        // 心跳检测重置
        HeartCheck();
    }

    void OnMessageReceived(WebSocket ws, string message)
    {
        // 如果获取到消息,心跳检测重置
        // 拿到任何消息都说明当前连接是正常的
        HeartCheck();
        Debug.Log(message);
    }

    void OnClosed(WebSocket ws, UInt16 code, string message)
    {
        Debug.Log("websocket关闭," + message);
        webSocket = null;
        ReConnect();
    }

    void OnError(WebSocket ws, Exception ex)
    {
        if(ex!=null)
            Debug.Log("websocket连接异常:" + ex.Message);
        webSocket = null;
        ReConnect();

    }

    void ReConnect()
    {
        if (this.lockReconnect)
            return;
        this.lockReconnect = true;
        StartCoroutine(SetReConnect());
    }

    private IEnumerator SetReConnect()
    {
        Debug.Log("正在重连websocket");
        yield return new WaitForSeconds(5);
        CreateWebSocket();
        lockReconnect = false;
    }

    //心跳检测
    private void HeartCheck()
    {
        if(_clientPing!=null)
        {
            StopCoroutine(_clientPing);
            _clientPing = null;
        }
        if(_serverPing!=null)
        {
            StopCoroutine(_serverPing);
            _serverPing = null;
        }
        _clientPing = StartCoroutine(ClientPing());
    }

    // 这里发送一个心跳,后端收到后,返回一个心跳消息
    // onmessage拿到返回的心跳就说明连接正常
    private IEnumerator ClientPing()
    {
        yield return new WaitForSeconds(5);
        Send("heartbeat");
        _serverPing = StartCoroutine(ServerPing());
    }
    // 如果超过一定时间还没重置,说明后端主动断开了
    // 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
    private IEnumerator ServerPing()
    {
        yield return new WaitForSeconds(5);
        webSocket.Close();
    }
    
    //发送心跳
    private IEnumerator HeartPing()
    {
        while(true)
        {
            yield return new WaitForSeconds(5);
            this.Send("heartbeat");
        }
    }
    //向服务端发送信息
    private void Send(string msg)
    {
        if (webSocket == null || string.IsNullOrEmpty(msg)) return;
        if(webSocket.IsOpen)
        {
            webSocket.Send(msg);
        }
    }

}
  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity中的WebSocket断线重连可以通过以下步骤实现: 1. 创建WebSocket连接:使用UnityWebSocket库创建WebSocket连接。 2. 监听WebSocket连接状态:使用WebSocket库提供的事件监听WebSocket连接状态,当WebSocket连接断开时触发重连操作。 3. 实现重连操作:在WebSocket连接断开时,使用定时器或者协程实现重连操作。在重连操作中,重新创建WebSocket连接,并重新注册事件监听。 4. 处理异常情况:在重连过程中,可能会遇到网络异常等情况,需要进行异常处理,例如记录日志、提示用户等。 以下是一个简单的代码示例: ```csharp using UnityEngine; using WebSocketSharp; public class WebSocketManager : MonoBehaviour { private WebSocket webSocket; private bool connected = false; void Start() { Connect(); } void OnDestroy() { if (webSocket != null) { webSocket.Close(); } } private void Connect() { if (webSocket != null) { webSocket.Close(); } webSocket = new WebSocket("ws://localhost:8080"); webSocket.OnOpen += (sender, e) => { connected = true; Debug.Log("WebSocket connected"); }; webSocket.OnClose += (sender, e) => { connected = false; Debug.Log("WebSocket disconnected"); Reconnect(); }; webSocket.OnError += (sender, e) => { Debug.Log("WebSocket error: " + e.Message); }; webSocket.Connect(); } private void Reconnect() { if (!connected) { Debug.Log("Reconnecting..."); Invoke("Connect", 5f); // 5秒后重连 } } } ``` 在上述示例中,当WebSocket连接断开时,会触发重连操作。重连操作使用了Unity的Invoke方法,延迟5秒后重新连接WebSocket。如果WebSocket连接成功,会触发OnOpen事件,设置connected标志位为true。如果WebSocket连接断开,会触发OnClose事件,设置connected标志位为false,并再次触发重连操作。如果WebSocket连接出现异常,会触发OnError事件,输出错误信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值