123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- #if UNITY_WEBGL // && !UNITY_EDITOR
- using System;
- namespace XGame.Framework.Network.Web
- {
- public class WebSocket : IRemoteSession, IDisposable
- {
- internal WebSocketState ReadyState => (WebSocketState)WebSocketService.WebSocketGetState(instanceId);
- private volatile SessionStatus _status = SessionStatus.FREE;
- public SessionStatus Status => _status;
- public SessionAddress Address { get; private set; }
- internal int instanceId = 0;
- private ISessionContext _context;
- internal WebSocket(ISessionContext context)
- {
- _context = context;
- }
- //public WebSocket(string address)
- //{
- // this.Address = address;
- // AllocateInstance();
- //}
- //public WebSocket(string address, string subProtocol)
- //{
- // this.Address = address;
- // this.SubProtocols = new string[] { subProtocol };
- // AllocateInstance();
- //}
- //public WebSocket(string address, string[] subProtocols)
- //{
- // this.Address = address;
- // this.SubProtocols = subProtocols;
- // AllocateInstance();
- //}
- //internal void AllocateInstance()
- //{
- // instanceId = WebSocketService.AllocateInstance(this.Address);
- // Log($"Allocate socket with instanceId: {instanceId}");
- // if (this.SubProtocols == null) return;
- // foreach (var protocol in this.SubProtocols)
- // {
- // if (string.IsNullOrEmpty(protocol)) continue;
- // Log($"Add Sub Protocol {protocol}, with instanceId: {instanceId}");
- // int code = WebSocketService.WebSocketAddSubProtocol(instanceId, protocol);
- // if (code < 0)
- // {
- // HandleOnError(GetErrorMessageFromCode(code));
- // break;
- // }
- // }
- //}
- //~WebSocket()
- //{
- // Log($"Free socket with instanceId: {instanceId}");
- // WebSocketService.WebSocketFree(instanceId);
- //}
- //public void ConnectAsync()
- //{
- // Log($"Connect with instanceId: {instanceId}");
- // WebSocketService.Add(this);
- // int code = WebSocketService.WebSocketConnect(instanceId);
- // if (code < 0) HandleOnError(GetErrorMessageFromCode(code));
- //}
- //public void CloseAsync()
- //{
- // Log($"Close with instanceId: {instanceId}");
- // int code = WebSocketService.WebSocketClose(instanceId, (int)CloseStatusCode.Normal, "Normal Closure");
- // if (code < 0) HandleOnError(GetErrorMessageFromCode(code));
- //}
- //public void SendAsync(string text)
- //{
- // Log($"Send, type: {Opcode.Text}, size: {text.Length}");
- // int code = WebSocketService.WebSocketSendStr(instanceId, text);
- // if (code < 0) HandleOnError(GetErrorMessageFromCode(code));
- //}
- //public void SendAsync(byte[] data)
- //{
- // Log($"Send, type: {Opcode.Binary}, size: {data.Length}");
- // int code = WebSocketService.WebSocketSend(instanceId, data, data.Length);
- // if (code < 0) HandleOnError(GetErrorMessageFromCode(code));
- //}
- internal void HandleOnOpen()
- {
- Log.Debug($"[WebSocket] OnOpen.");
- _status = SessionStatus.CONNECTED;
- _context.Synchronizer.Enqueue(ESessionCode.Connected, null);
- }
- internal void HandleOnMessage(byte[] rawData, int offset, int length)
- {
- Log.Debug($"[WebSocket] OnMessage.");
- _context.Synchronizer.Enqueue(rawData, offset, length);
- }
- internal void HandleOnMessageStr(string data)
- {
- Log.Error($"[WebSocket] OnMessageStr. data:{data}");
- }
- internal void HandleOnClose(ushort code, string reason)
- {
- Log.Debug($"[WebSocket] OnClose, code: {code}, reason: {reason}");
- if (code != (int)CloseStatusCode.Normal)
- OnDisconnectError(new WebSocketException(reason, code));
- OnDisconnect();
- }
- internal void HandleOnError(string msg)
- {
- Log.Debug("[WebSocket] OnError, error: " + msg);
- OnReceiveError(new WebSocketException(msg, 0));
- }
- internal static Exception GetErrorMessageFromCode(int errorCode)
- {
- string message;
- switch (errorCode)
- {
- case -1:
- message = "WebSocket instance not found.";
- break;
- case -2:
- message = "WebSocket is already connected or in connecting state.";
- break;
- case -3:
- message = "WebSocket is not connected.";
- break;
- case -4:
- message = "WebSocket is already closing.";
- break;
- case -5:
- message = "WebSocket is already closed.";
- break;
- case -6:
- message = "WebSocket is not in open state.";
- break;
- case -7:
- message = "Cannot close WebSocket, An invalid code was specified or reason is too long.";
- break;
- case -8:
- message = "Not support buffer slice. ";
- break;
- default:
- message = $"Unknown error code {errorCode}.";
- break;
- }
- return new WebSocketException(message, errorCode);
- }
- //[System.Diagnostics.Conditional("UNITY_WEB_SOCKET_LOG")]
- //static void Log(string msg)
- //{
- // var time = DateTime.Now.ToString("HH:mm:ss.fff");
- // UnityEngine.Debug.Log($"[{time}][UnityWebSocket] {msg}");
- //}
- public void Connect(AddressInfo info)
- {
- if (Status != SessionStatus.FREE)
- {
- Log.Warn($"[WebSocket] SessionStatus:{Status} 已连接或者正在连接,又尝试连接");
- return;
- }
- OnStartConnect();
- if (Address == null ||
- Address.Domain != info.Address ||
- Address.PORT == info.Port ||
- Address.ProtocolType == info.ProtocolType)
- {
- Address = new SessionAddress(info);
- }
- var uri = GetUri(Address);
- if (string.IsNullOrEmpty(uri))
- {
- OnConnectFail(new Exception($"[WebSocket] ProtocolType {Address.ProtocolType} is not find"));
- return;
- }
- instanceId = WebSocketService.AllocateInstance(uri);
- WebSocketService.Add(this);
- int code = WebSocketService.WebSocketConnect(instanceId);
- if (code < 0)
- OnConnectFail(GetErrorMessageFromCode(code));
- }
- public bool IsConnected(bool bPrecice)
- {
- return Status == SessionStatus.CONNECTED && ReadyState == WebSocketState.Open;
- }
- public void Disconnect()
- {
- if (Status == SessionStatus.FREE)
- return;
- _status = SessionStatus.FREE;
- int code = WebSocketService.WebSocketClose(instanceId, (int)CloseStatusCode.Normal, "Normal Closure");
- if (code < 0)
- OnDisconnectError(GetErrorMessageFromCode(code));
- //else
- // OnDisconnect();
- }
- public bool Send(byte[] bytes, int offset, int length)
- {
- // offset 固定为零
- int code = WebSocketService.WebSocketSend(instanceId, bytes, length);
- if (code < 0)
- OnSendError(GetErrorMessageFromCode(code));
- SessionBufferPool.Recycle(bytes);
- return code >= 0;
- }
- void IDisposable.Dispose()
- {
- Disconnect();
- _context = null;
- WebSocketService.WebSocketFree(instanceId);
- }
- string GetUri(SessionAddress info)
- {
- string url;
- switch (info.ProtocolType)
- {
- case ProtocolType.WS:
- if (string.IsNullOrEmpty(info.URI))
- url = $"ws://{info.Domain}:{info.PORT}";
- else
- url = info.URI;
- break;
- case ProtocolType.WSS:
- if (string.IsNullOrEmpty(info.URI))
- url = $"wss://{info.Domain}:{info.PORT}";
- else
- url = info.URI;
- break;
- default:
- return url = string.Empty;
- }
- return url;
- }
- #region Event
- private void OnConnectFail(Exception e)
- {
- _status = SessionStatus.CONNECT_FAIL;
- _context.Synchronizer.Enqueue(ESessionCode.ConnectFail, e);
- }
- //private void OnConnectTimeout()
- //{
- // _status = SessionStatus.CONNECT_TIMEOUT;
- // _context.Synchronizer.Enqueue(ESessionCode.ConnectTimeout, null);
- //}
- //private void OnConnected()
- //{
- // _status = SessionStatus.CONNECTED;
- // _context.Synchronizer.Enqueue(ESessionCode.Connected, null);
- //}
- private void OnStartConnect()
- {
- _context.Synchronizer.Enqueue(ESessionCode.StartConnect, null);
- }
- private void OnDisconnect()
- {
- _context.Synchronizer.Enqueue(ESessionCode.Disconnect, null);
- }
- private void OnDisconnectError(Exception e)
- {
- _context.Synchronizer.Enqueue(ESessionCode.DisconnectError, e);
- }
- private void OnSendError(Exception e)
- {
- _status = SessionStatus.SEND_ERROR;
- _context.Synchronizer.Enqueue(ESessionCode.SendException, e);
- }
- private void OnReceiveError(Exception e)
- {
- _status = SessionStatus.RECV_ERROR;
- _context.Synchronizer.Enqueue(ESessionCode.RecvError, e);
- }
- //private void OnRemoteClose()
- //{
- // _status = SessionStatus.CLOSED;
- // _context.Synchronizer.Enqueue(ESessionCode.SessionClose, null);
- //}
- #endregion
- }
- }
- #endif
|