| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #if UNITY_WEBGL
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Net;
- using System.Runtime.InteropServices.ComTypes;
- using BestHTTP.WebSocket;
- using GFGGame;
- namespace ET
- {
- public class WChannel : AChannel
- {
- private readonly WService Service;
- private WebSocket webSocket;
- private Queue<MemoryStream> waitSend = new Queue<MemoryStream>();
- //address=http://webgltest.goufuguiwxw.com/ws
- public WChannel(long id, IPEndPoint ipEndPoint, WService service, string address)
- {
- this.Service = service;
- this.ChannelType = ChannelType.Connect;
- this.Id = id;
- string wsStr;
- bool isHttps = LauncherConfig.isHttps;
-
- // 检查address是否是URL格式
- if (!string.IsNullOrEmpty(address) && (address.StartsWith("http://") || address.StartsWith("https://")))
- {
- // 如果是URL格式,转换为WebSocket协议
- if (address.StartsWith("https://"))
- {
- wsStr = address.Replace("https://", "wss://");
- isHttps = true;
- }
- else
- {
- wsStr = address.Replace("http://", "ws://");
- }
- }
- else if (ipEndPoint != null)
- {
- // 如果不是URL格式但有IPEndPoint,使用IP+端口方式
- wsStr = $"ws://{ipEndPoint}";
- }
- else if (!string.IsNullOrEmpty(address))
- {
- // 如果没有IPEndPoint但有address,直接使用address作为WebSocket地址
- // 支持IP:端口格式
- wsStr = address.StartsWith("ws://") || address.StartsWith("wss://") ? address : $"ws://{address}";
- }
- else
- {
- // 无法构造WebSocket地址
- Log.Error($"WChannel: Invalid address and ipEndPoint are both null");
- throw new ArgumentException("Invalid address and ipEndPoint are both null");
- }
- Log.Debug($"wc address:{address}");
- Log.Debug($"wc wsStr:{wsStr}");
- WebSocket ws = new WebSocket(new Uri(wsStr));
- if (isHttps || ipEndPoint == null)
- {
- this.RemoteAddress = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
- }
- else
- {
- this.RemoteAddress = ipEndPoint;
- }
- // Subscribe to the WS events
- ws.OnOpen += OnOpen;
- ws.OnClosed += OnClosed;
- ws.OnError += OnError;
- ws.OnBinary += OnRead;
- // Start connecting to the server
- ws.Open();
- }
- public override void Dispose()
- {
- if (this.IsDisposed)
- {
- return;
- }
- this.Id = 0;
- this.webSocket?.Close();
- this.webSocket = null;
- }
- public void Send(MemoryStream memoryBuffer)
- {
- switch (this.Service.ServiceType)
- {
- case ServiceType.Inner:
- break;
- case ServiceType.Outer:
- memoryBuffer.Seek(Packet.ActorIdLength, SeekOrigin.Begin);
- ;
- break;
- }
- if (this.webSocket == null)
- {
- this.waitSend.Enqueue(memoryBuffer);
- return;
- }
- SendOne(memoryBuffer);
- }
- private void SendOne(MemoryStream memoryBuffer)
- {
- this.webSocket.Send(memoryBuffer.GetBuffer(), (ulong)memoryBuffer.Position,
- (ulong)(memoryBuffer.Length - memoryBuffer.Position));
- }
- private void OnOpen(WebSocket ws)
- {
- if (ws == null)
- {
- this.OnError(ErrorCore.ERR_WebsocketConnectError);
- return;
- }
- if (this.IsDisposed)
- {
- return;
- }
- this.webSocket = ws;
- while (this.waitSend.Count > 0)
- {
- MemoryStream memoryBuffer = this.waitSend.Dequeue();
- this.SendOne(memoryBuffer);
- }
- }
- /// <summary>
- /// Called when we received a text message from the server
- /// </summary>
- private void OnRead(WebSocket ws, byte[] data)
- {
- if (this.IsDisposed)
- {
- return;
- }
- MemoryStream memoryBuffer = this.Service.Fetch();
- memoryBuffer.Write(data, 0, data.Length); // 写入整个 data
- memoryBuffer.Seek(2, SeekOrigin.Begin);
- this.Service.ReadCallback(this.Id, memoryBuffer);
- }
- /// <summary>
- /// Called when the web socket closed
- /// </summary>
- private void OnClosed(WebSocket ws, UInt16 code, string message)
- {
- if (this.IsDisposed)
- {
- return;
- }
- Log.Error($"wchannel closed: {code} {message}");
- this.OnError(0);
- }
- /// <summary>
- /// Called when an error occured on client side
- /// </summary>
- private void OnError(WebSocket ws, string error)
- {
- if (this.IsDisposed)
- {
- return;
- }
- //Log.Error($"WChannel error: {this.Id} {ws.GetHashCode()} {error}");
- this.OnError(ErrorCore.ERR_WebsocketError);
- }
- private void OnError(int error)
- {
- Log.Info($"WChannel error: {this.Id} {error}");
- long channelId = this.Id;
- this.Service.Remove(channelId);
- this.Service.ErrorCallback(channelId, error);
- }
- }
- }
- #endif
|