一、简介
WebSocket
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
WebSocket与http
其实从历史上来讲,websocket是为了克服http无法双向通信而引入的,在通常的使用中,可以复用http的端口与功能,除此外,他们没有其他的联系,而是完全是独立的协议,通常情况下,http是单向的web 服务,而websocket是全双工的,服务器和客户端可以实时的传输信息,在引用时他们可以在http服务器上同时部署,特别是在NodeJs中。
WebSocket与Socket
那么websocket和socket是什么关系呢? 其实可以理解为websocket是在socket的基础上实现的,其基于消息帧和TCP协议,而socket更通用,在编程中,可以选在tcp,udp,也需要自己控制数据流格式,每次的数据的长度都需要自己控制与读取。
二、使用
Best HTTP插件:这款插件不但支持WebSockets,还支持HTTP,Sockets等通信方式是一款不错的插件。也支持打包Webgl。下边记录两种Unity客户端使用WebSocket的方法。
插件
绑定
将插件包拖入unity然后在代码里引入插件类,最后写代码
代码
using UnityEngine;
using System;
using BestHTTP.WebSocket;
using System.Collections;public class WebSocketClient : MonoBehaviour
{public string address = "ws://127.0.0.1:8002";WebSocket webSocket;private bool lockReconnect = false;private Coroutine _pingCor, _clientPing, _serverPing;private void Start(){CreateWebSocket();}private void Update(){Debug.Log(lockReconnect);}/** 创建并初始化连接 start -------------------------------------------------------------------------------------------------------------------*/void CreateWebSocket(){try{webSocket = new WebSocket(new Uri(address));
#if !UNITY_WEBGLwebSocket.StartPingThread = true;
#endifInitHandle();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连接成功");webSocket.Send("一个客户端连过来了");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.LogFormat("OnClosed: code={0}, msg={1}", code, message);webSocket = null;ReConnect();}void OnError(WebSocket ws, string ex){string errorMsg = string.Empty;
#if !UNITY_WEBGL || UNITY_EDITORif (ws.InternalRequest.Response != null){errorMsg = string.Format("Status Code from Server: {0} and Message: {1}", ws.InternalRequest.Response.StatusCode, ws.InternalRequest.Response.Message);}
#endifDebug.LogFormat("OnError: error occured: {0}\n", (ex != null ? ex : "Unknown Error " + errorMsg));webSocket = null;ReConnect();}//end -------------------------------------------------------------------------------------------------------------------/** 发送信息*/public void WebSend(string msg){if (webSocket == null || string.IsNullOrEmpty(msg)) return;if (webSocket.IsOpen){webSocket.Send(msg);}}/** 关闭连接*/public void OnClose(){webSocket.Close(1000, "Bye!");}/** 重新连接*/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;}/** 心跳检测 start -------------------------------------------------------------------------------------------------------------------*/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);WebSend("heartbeat");_serverPing = StartCoroutine(ServerPing());}/** 如果超过一定时间还没重置,说明后端主动断开了* 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次*/private IEnumerator ServerPing(){yield return new WaitForSeconds(5);if (webSocket != null){webSocket.Close();}}private IEnumerator HeartPing(){while (true){yield return new WaitForSeconds(5);this.WebSend("Heartbeat");}}//end -------------------------------------------------------------------------------------------------------------------}