From 18e418ca0b5354d464f242be08958b90ee8d779a Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期五, 06 二月 2026 14:59:24 +0800
Subject: [PATCH] TCP/WEBSOCKET SUPPORT

---
 Main/Core/NetworkPackage/Socket/ClientSocket.cs |  397 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 324 insertions(+), 73 deletions(-)

diff --git a/Main/Core/NetworkPackage/Socket/ClientSocket.cs b/Main/Core/NetworkPackage/Socket/ClientSocket.cs
index 3055fe0..bf072a0 100644
--- a/Main/Core/NetworkPackage/Socket/ClientSocket.cs
+++ b/Main/Core/NetworkPackage/Socket/ClientSocket.cs
@@ -1,39 +1,73 @@
 锘縰sing UnityEngine;
 using System;
-using System.Collections;
 using System.Collections.Generic;
+
+#if !UNITY_WEBGL && !H5_VERSION
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
+#else
+using NativeWebSocket;
+using Cysharp.Threading.Tasks;
+#endif
 
+/// <summary>
+/// 缁熶竴鐨勭綉缁淪ocket绫� - 鑷姩閫傞厤TCP Socket鍜學ebSocket
+/// TCP Socket: Windows, Mac, iOS, Android绛夊钩鍙�
+/// WebSocket: WebGL/寰俊灏忔父鎴忕瓑Web骞冲彴
+/// </summary>
 public class ClientSocket
 {
     GameNetEncode encoder = new GameNetEncode();
+    
+#if !UNITY_WEBGL && !H5_VERSION
+    // TCP Socket 瀹炵幇锛堥潪WebGL骞冲彴锛�
     Socket m_Socket;
     public Socket socket { get { return m_Socket; } }
-
     private Thread m_packageThread;
-    private byte[] bufferBytes = new byte[4096];                       // 4K锛屽崟鍖呭瓧鑺傛暟缁勭紦瀛�
-    private byte[] fragmentBytes;                                               //鐣欏寘鍚庣殑鍐呭
-    private long getBytesTotal = 0;                                            //鍙戦�佺殑鏁版嵁鎬婚噺
-    private long sendBytesTotal = 0;                                         //鍙戦�佺殑鏁版嵁鎬婚噺
+    private byte[] bufferBytes = new byte[4096];
+    private byte[] fragmentBytes; // TCP鍒嗗寘缂撳瓨
+    bool isStopTreading = false;
+#else
+    // WebSocket 瀹炵幇锛圵ebGL骞冲彴锛�
+    WebSocket webSocket;
+    public WebSocket socket { get { return webSocket; } }
+#endif
 
-    public bool connected { get { return m_Socket == null ? false : m_Socket.Connected; } }
+    public Action OnDisconnected;
+
+    private long getBytesTotal = 0;
+    private long sendBytesTotal = 0;
+    
+    public bool connected 
+    { 
+        get 
+        {
+#if !UNITY_WEBGL && !H5_VERSION
+            return m_Socket == null ? false : m_Socket.Connected;
+#else
+            return webSocket != null && webSocket.State == WebSocketState.Open;
+#endif
+        } 
+    }
 
     ServerType socketType = ServerType.Main;
     DateTime m_LastPackageTime;
     public DateTime lastPackageTime { get { return m_LastPackageTime; } }
 
-    bool isStopTreading = false;
-
     string ip;
     int port;
     Action<bool> onConnected = null;
+    Queue<byte[]> sendQueue = new Queue<byte[]>();
+    static byte[] vCmdBytes = new byte[2];
 
     public ClientSocket(ServerType type)
     {
         this.socketType = type;
     }
+
+#if !UNITY_WEBGL && !H5_VERSION
+    // ==================== TCP Socket 瀹炵幇 ====================
 
     public void Connect(string _ip, int _port, Action<bool> _onConnected)
     {
@@ -260,7 +294,6 @@
 
     }
 
-    static byte[] vCmdBytes = new byte[2];
     /// <summary>
     /// 瑙f瀽鏁版嵁鍖咃細 FFCC+灏佸寘闀垮害+灏佸寘锛堝皝鍖呭ご+鏁版嵁锛夌粨鏋勪綋鍐呭
     /// </summary>
@@ -346,71 +379,14 @@
 
     }
 
-    /// <summary>
-    /// 鍙戦�佷俊鎭�
-    /// </summary>
-    public void SendInfo(GameNetPackBasic protocol)
-    {
-        if (!connected)
-        {
-            return;
-        }
-
-        if (protocol == null)
-        {
-            Debug.LogError("瑕佸彂鐨勪俊鎭璞′负绌�");
-            return;
-        }
-
-        // if (Launch.Instance.EnableNetLog)
-        // {
-        //     Debug.LogFormat("鍙戝寘锛歿0}", protocol.GetType().Name);
-        // }
-
-        if (protocol.combineBytes == null)
-        {
-            protocol.WriteToBytes();
-        }
-        protocol.CombineDatas(encoder);
-#if UNITY_EDITOR
-        NetPkgCtl.RecordPackage(socketType, protocol.vInfoCont, NetPackagetType.Client, protocol.ToString(), FieldPrint.PrintFields(protocol), FieldPrint.PrintFieldsExpand(protocol, true));
-#endif
-        sendBytesTotal += protocol.combineBytes.Length;
-        SendBytes(protocol.combineBytes);
-    }
-
-    /// <summary>
-    /// 鍙戦�佷俊鎭�
-    /// </summary>
-    /// <param name="vBytes"></param>
-    public void SendInfo(byte[] vBytes)
-    {
-        if (!connected)
-        {
-            Debug.LogError("灏氭湭涓庤鍚庣閾炬帴锛佹棤娉曞彂閫佷俊鎭�");
-            return;
-        }
-
-        if (vBytes == null || vBytes.Length < 2)
-        {
-            Debug.LogError("瑕佸彂鐨勪俊鎭暟鎹负绌烘垨鏁版嵁涓嶈冻");
-            return;
-        }
-
-        vBytes = encoder.BaseXorAdd(vBytes);
-        byte[] vFrameHead = new byte[] { 255, 204 };
-        byte[] vMsgBodyLength = BitConverter.GetBytes(vBytes.Length);
-        byte[] vTotal = new byte[vBytes.Length + 6];
-        Array.Copy(vFrameHead, 0, vTotal, 0, vFrameHead.Length);
-        Array.Copy(vMsgBodyLength, 0, vTotal, 2, vMsgBodyLength.Length);
-        Array.Copy(vBytes, 0, vTotal, 6, vBytes.Length);
-
-        SendBytes(vTotal);
-    }
-
-    Queue<byte[]> sendQueue = new Queue<byte[]>();
+    // TCP Socket 鐨� SendBytes锛堢鏈夋柟娉曪紝鐢辩粺涓�鐨� SendInfo 璋冪敤锛�
     private void SendBytes(byte[] bytes)
     {
+        // 璋冭瘯鏃ュ織锛氳緭鍑哄彂閫佺殑瀛楄妭鏁版嵁
+        // string hexString = "[TCP] SendBytes Length=" + bytes.Length + " Data=" + BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 32)).Replace("-", " ");
+        // if (bytes.Length > 32) hexString += "...";
+        // Debug.Log(hexString);
+        
         try
         {
             if (sendQueue.Count > 0)
@@ -448,4 +424,279 @@
         }
     }
 
+    public void DispatchMessageQueue()
+    {
+        // TCP涓嶉渶瑕佽疆璇�
+    }
+
+#else
+    // ==================== WebSocket 瀹炵幇锛圵ebGL骞冲彴锛�====================
+    
+    public async void Connect(string _ip, int _port, Action<bool> _onConnected)
+    {
+        ip = _ip;
+        port = _port;
+        onConnected = _onConnected;
+        
+        string url = $"ws://{_ip}:{_port}";
+        Debug.Log($"[ClientSocket-WebSocket] 寮�濮嬭繛鎺�: {url}");
+        
+        try
+        {
+            webSocket = new WebSocket(url);
+            
+            // 娉ㄥ唽WebSocket鍥炶皟
+            webSocket.OnOpen += OnWebSocketOpen;
+            webSocket.OnMessage += OnWebSocketMessage;
+            webSocket.OnError += OnWebSocketError;
+            webSocket.OnClose += OnWebSocketClose;
+            
+            await webSocket.Connect();
+        }
+        catch (Exception ex)
+        {
+            Debug.LogError($"[ClientSocket-WebSocket] 杩炴帴寮傚父: {ex.Message}");
+            if (onConnected != null)
+            {
+                onConnected(false);
+                onConnected = null;
+            }
+        }
+    }
+    
+    private void OnWebSocketOpen()
+    {
+        Debug.Log("[ClientSocket-WebSocket] 杩炴帴鎴愬姛");
+        m_LastPackageTime = DateTime.Now;
+        
+        if (onConnected != null)
+        {
+            onConnected(true);
+            onConnected = null;
+        }
+    }
+    
+    private void OnWebSocketMessage(byte[] data)
+    {
+        try
+        {
+            getBytesTotal += data.Length;
+            
+            // WebSocket鏄秷鎭ā寮忥紝姣忔鏀跺埌瀹屾暣鍖咃紝鐩存帴澶勭悊
+            byte[] fixBytes = data;
+            int vReadIndex = 0;
+            byte[] vPackBytes;
+            int vLeavingLeng = 0;
+            int vBodyLeng = 0;
+            int vTotalLeng = fixBytes.Length;
+            GameNetPackBasic vNetpack;
+
+            while (vReadIndex < vTotalLeng)
+            {
+                vLeavingLeng = vTotalLeng - vReadIndex;
+                if (vLeavingLeng < 6)
+                {
+                    Debug.LogError($"[ClientSocket-WebSocket] 鍖呮暟鎹笉瓒�: {vLeavingLeng} bytes");
+                    break;
+                }
+                
+                vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
+                if (vBodyLeng > vLeavingLeng - 6)
+                {
+                    Debug.LogError($"[ClientSocket-WebSocket] 鍖呴暱搴︿笉鍖归厤: 澹版槑 {vBodyLeng + 6}, 瀹為檯 {vLeavingLeng}");
+                    break;
+                }
+                
+                vPackBytes = new byte[vBodyLeng];
+                Array.Copy(fixBytes, vReadIndex + 6, vPackBytes, 0, vBodyLeng);
+
+                vPackBytes = encoder.BaseXorSub(vPackBytes);
+                Array.Copy(vPackBytes, 0, vCmdBytes, 0, 2);
+                var cmd = (ushort)((ushort)(vCmdBytes[0] << 8) + vCmdBytes[1]);
+                bool isRegist = false;
+
+                if (PackageRegedit.Contain(cmd))
+                {
+                    vNetpack = PackageRegedit.TransPack(socketType, cmd, vPackBytes);
+                    if (vNetpack != null)
+                    {
+                        m_LastPackageTime = DateTime.Now;
+                        GameNetSystem.Instance.PushPackage(vNetpack, socketType);
+                        isRegist = true;
+                    }
+                }
+
+                vReadIndex += 6 + vBodyLeng;
+
+                if (!isRegist)
+                {
+#if UNITY_EDITOR
+                    PackageRegedit.TransPack(socketType, cmd, vPackBytes);
+#endif
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            Debug.LogError($"[ClientSocket-WebSocket] 鏀跺寘寮傚父锛歿ex}");
+        }
+    }
+    
+    private void OnWebSocketError(string error)
+    {
+        Debug.LogError($"[ClientSocket-WebSocket] 閿欒: {error}");
+    }
+    
+    private void OnWebSocketClose(WebSocketCloseCode code)
+    {
+        Debug.Log($"[ClientSocket-WebSocket] 杩炴帴鍏抽棴: {code}");
+        OnDisconnected?.Invoke();
+    }
+    
+    public async void CloseConnect()
+    {
+        Debug.Log("[ClientSocket-WebSocket] ==== CloseConnect");
+        
+        if (webSocket != null)
+        {
+            sendQueue.Clear();
+            await webSocket.Close();
+            webSocket = null;
+        }
+    }
+    
+    private bool isSending = false;
+    
+    private async void SendBytes(byte[] bytes)
+    {
+        // 璋冭瘯鏃ュ織锛氳緭鍑哄彂閫佺殑瀛楄妭鏁版嵁
+        // string hexString = "[WebSocket] SendBytes Length=" + bytes.Length + " Data=" + BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 32)).Replace("-", " ");
+        // if (bytes.Length > 32) hexString += "...";
+        // Debug.Log(hexString);
+        
+        if (webSocket == null || webSocket.State != WebSocketState.Open)
+        {
+            Debug.LogError("[ClientSocket-WebSocket] 鏈繛鎺ワ紝鏃犳硶鍙戦��");
+            return;
+        }
+        
+        // 闃熷垪鏈哄埗
+        lock (sendQueue)
+        {
+            if (isSending)
+            {
+                sendQueue.Enqueue(bytes);
+                return;
+            }
+            isSending = true;
+        }
+        
+        try
+        {
+            await webSocket.Send(bytes);
+            
+            // 澶勭悊闃熷垪涓殑涓嬩竴涓�
+            lock (sendQueue)
+            {
+                if (sendQueue.Count > 0)
+                {
+                    byte[] nextBytes = sendQueue.Dequeue();
+                    isSending = false;
+                    SendBytes(nextBytes); // 閫掑綊鍙戦��
+                }
+                else
+                {
+                    isSending = false;
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            Debug.LogError($"[ClientSocket-WebSocket] 鍙戦�佸紓甯�: {ex.Message}");
+            lock (sendQueue)
+            {
+                isSending = false;
+            }
+        }
+    }
+    
+    // WebGL闇�瑕佸湪Update涓疆璇㈡秷鎭�
+    public void DispatchMessageQueue()
+    {
+// #if !UNITY_EDITOR
+        webSocket?.DispatchMessageQueue();
+// #endif
+    }
+    
+#endif
+
+    // ==================== 缁熶竴鐨勫叕鍏辨帴鍙o紙涓や釜骞冲彴閫氱敤锛�====================
+    
+    /// <summary>
+    /// 鍙戦�佸崗璁寘
+    /// </summary>
+    public void SendInfo(GameNetPackBasic protocol)
+    {
+        if (!connected)
+        {
+            return;
+        }
+
+        if (protocol == null)
+        {
+            Debug.LogError("瑕佸彂鐨勪俊鎭璞′负绌�");
+            return;
+        }
+
+        if (protocol.combineBytes == null)
+        {
+            protocol.WriteToBytes();
+        }
+        protocol.CombineDatas(encoder);
+        
+#if UNITY_EDITOR
+        NetPkgCtl.RecordPackage(socketType, protocol.vInfoCont, NetPackagetType.Client, 
+            protocol.ToString(), FieldPrint.PrintFields(protocol), FieldPrint.PrintFieldsExpand(protocol, true));
+#endif
+        
+        // 璋冭瘯鏃ュ織锛氭煡鐪� combineBytes 鐨勫唴瀹�
+        string hexString = "[SendInfo] Protocol=" + protocol.ToString() + " combineBytes.Length=" + protocol.combineBytes.Length + 
+            " Data=" + BitConverter.ToString(protocol.combineBytes, 0, Math.Min(protocol.combineBytes.Length, 32)).Replace("-", " ");
+        if (protocol.combineBytes.Length > 32) hexString += "...";
+        Debug.Log(hexString);
+        
+        sendBytesTotal += protocol.combineBytes.Length;
+        SendBytes(protocol.combineBytes);
+    }
+
+#if UNITY_EDITOR
+    /// <summary>
+    /// 鍙戦�佸師濮嬪瓧鑺傛暟鎹�
+    /// </summary>
+    public void SendInfo(byte[] vBytes)
+    {
+        if (!connected)
+        {
+            Debug.LogError("灏氭湭涓庤鍚庣閾炬帴锛佹棤娉曞彂閫佷俊鎭�");
+            return;
+        }
+
+        if (vBytes == null || vBytes.Length < 2)
+        {
+            Debug.LogError("瑕佸彂鐨勪俊鎭暟鎹负绌烘垨鏁版嵁涓嶈冻");
+            return;
+        }
+
+        // 鍔犲瘑骞剁粍瑁呭寘澶�
+        vBytes = encoder.BaseXorAdd(vBytes);
+        byte[] vFrameHead = new byte[] { 255, 204 };
+        byte[] vMsgBodyLength = BitConverter.GetBytes(vBytes.Length);
+        byte[] vTotal = new byte[vBytes.Length + 6];
+        Array.Copy(vFrameHead, 0, vTotal, 0, vFrameHead.Length);
+        Array.Copy(vMsgBodyLength, 0, vTotal, 2, vMsgBodyLength.Length);
+        Array.Copy(vBytes, 0, vTotal, 6, vBytes.Length);
+
+        SendBytes(vTotal);
+    }
+#endif
 }

--
Gitblit v1.8.0