using UnityEngine;
|
using System;
|
using System.Collections.Generic;
|
|
#if !UNITY_WEBGL
|
using System.Net;
|
using System.Net.Sockets;
|
using System.Threading;
|
#else
|
using NativeWebSocket;
|
using Cysharp.Threading.Tasks;
|
#endif
|
|
/// <summary>
|
/// 统一的网络Socket类 - 自动适配TCP Socket和WebSocket
|
/// TCP Socket: Windows, Mac, iOS, Android等平台
|
/// WebSocket: WebGL/微信小游戏等Web平台
|
/// </summary>
|
public class ClientSocket
|
{
|
GameNetEncode encoder = new GameNetEncode();
|
|
#if !UNITY_WEBGL
|
// TCP Socket 实现(非WebGL平台)
|
Socket m_Socket;
|
public Socket socket { get { return m_Socket; } }
|
private Thread m_packageThread;
|
private byte[] bufferBytes = new byte[4096];
|
private byte[] fragmentBytes; // TCP分包缓存
|
bool isStopTreading = false;
|
#else
|
// WebSocket 实现(WebGL平台)
|
WebSocket webSocket;
|
public WebSocket socket { get { return webSocket; } }
|
private byte[] fragmentBytes; // TCP-to-WS网关按TCP缓冲区拆包,需要跨消息重组
|
#endif
|
|
public Action OnDisconnected;
|
|
private long getBytesTotal = 0;
|
private long sendBytesTotal = 0;
|
|
public bool connected
|
{
|
get
|
{
|
#if !UNITY_WEBGL
|
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; } }
|
|
string ip;
|
int port;
|
Action<bool> onConnected = null;
|
Queue<byte[]> sendQueue = new Queue<byte[]>();
|
static byte[] vCmdBytes = new byte[2];
|
#if UNITY_WEBGL
|
string webSocketUrl;
|
bool webSocketOpened;
|
#endif
|
|
public ClientSocket(ServerType type)
|
{
|
this.socketType = type;
|
}
|
|
#if !UNITY_WEBGL
|
// ==================== TCP Socket 实现 ====================
|
|
public void Connect(string _ip, int _port, Action<bool> _onConnected)
|
{
|
Debug.unityLogger.logEnabled = true;
|
try
|
{
|
ip = _ip;
|
port = _port;
|
onConnected = _onConnected;
|
Debug.Log($"[ClientSocket][Connect] 尝试连接: ip={_ip}, port={_port}");
|
//目前测试到异步两个问题
|
// 1. BeginGetHostAddresses 不明情况下会很久才回调,导致触发超时
|
// 2. 超时的情况下多次尝试登录后,会触发多次OnGetHostAddresses,导致登录异常
|
//Dns.BeginGetHostAddresses(_ip, OnGetHostAddresses, null);
|
|
IPAddress ipAddress;
|
#if UNITY_IPHONE
|
IPHostEntry ipAddresses = Dns.GetHostEntry(_ip);
|
ipAddress = ipAddresses.AddressList[0];
|
|
#else
|
IPAddress[] ipAddresses = Dns.GetHostAddresses(_ip);
|
ipAddress = ipAddresses[0];
|
#endif
|
|
Debug.Log($"[ClientSocket][Connect] 解析到ipAddress={ipAddress}, family={ipAddress.AddressFamily}");
|
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
{
|
Debug.Log("[ClientSocket][Connect] 当前使用的网络: IPV6");
|
m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
}
|
else
|
{
|
Debug.Log("[ClientSocket][Connect] 当前使用的网络: IPV4");
|
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
}
|
|
var ipEndPoint = new IPEndPoint(ipAddress, port);
|
if (ipEndPoint == null)
|
{
|
Debug.LogError("[ClientSocket][Connect] IpEndPoint is null");
|
}
|
|
m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), null);
|
}
|
catch (Exception e)
|
{
|
Debug.LogError($"[ClientSocket][Connect] 异常: {e.Message}");
|
}
|
|
|
}
|
|
private void OnGetHostAddresses(IAsyncResult _result)
|
{
|
var ipAddresses = Dns.EndGetHostAddresses(_result);
|
|
if (ipAddresses[0].AddressFamily == AddressFamily.InterNetworkV6)
|
{
|
Debug.Log("当前使用的网络: IPV6");
|
m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
}
|
else
|
{
|
Debug.Log("当前使用的网络: IPV4");
|
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
}
|
|
var ipEndPoint = new IPEndPoint(ipAddresses[0], port);
|
if (ipEndPoint == null)
|
{
|
Debug.Log("IpEndPoint is null");
|
}
|
|
m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), null);
|
}
|
|
/// <summary>
|
/// 链接成功时的回调
|
/// </summary>
|
/// <param name="_result"></param>
|
private void ConnectCallBack(IAsyncResult _result)
|
{
|
Debug.unityLogger.logEnabled = true;
|
if (!_result.IsCompleted)
|
{
|
Debug.LogError("[ClientSocket][ConnectCallBack] 链接超时!");
|
CloseConnect();
|
if (onConnected != null)
|
{
|
Debug.LogError("[ClientSocket][ConnectCallBack] onConnected(false) 超时");
|
onConnected(false);
|
onConnected = null;
|
}
|
}
|
else
|
{
|
try
|
{
|
if (m_Socket != null && m_Socket.Connected)
|
{
|
Debug.Log("[ClientSocket][ConnectCallBack] 确认的链接实现");
|
OnConnectSuccess();
|
}
|
else
|
{
|
Debug.LogError("[ClientSocket][ConnectCallBack] m_Socket为null或未连接");
|
if (m_Socket != null)
|
{
|
m_Socket.Disconnect(true);
|
}
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.LogError($"[ClientSocket][ConnectCallBack] 异常: {ex}");
|
}
|
finally
|
{
|
if (onConnected != null)
|
{
|
Debug.Log($"[ClientSocket][ConnectCallBack] onConnected({m_Socket != null && m_Socket.Connected})");
|
onConnected(m_Socket != null && m_Socket.Connected);
|
onConnected = null;
|
}
|
}
|
|
}
|
|
onConnected = null;
|
}
|
|
/// <summary>
|
/// 关闭链接
|
/// </summary>
|
public void CloseConnect()
|
{
|
Debug.Log("==== CloseConnect");
|
Debug.unityLogger.logEnabled = true;
|
Debug.Log("[ClientSocket][CloseConnect] ==== CloseConnect");
|
try
|
{
|
isStopTreading = true;
|
if (m_packageThread != null)
|
{
|
m_packageThread.Abort();
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
|
try
|
{
|
if (m_Socket != null && m_Socket.Connected)
|
{
|
m_Socket.Shutdown(SocketShutdown.Both);
|
m_Socket.Close();
|
}
|
}
|
catch (System.Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
|
sendQueue.Clear();
|
m_Socket = null;
|
}
|
|
/// <summary>
|
/// 链接成功
|
/// </summary>
|
private void OnConnectSuccess()
|
{
|
if (m_packageThread != null)
|
{
|
m_packageThread.Abort();
|
m_packageThread = null;
|
}
|
|
m_LastPackageTime = DateTime.Now;
|
m_packageThread = new Thread(new ThreadStart(ReceiveInfo)); // 启动线程接收信息
|
m_packageThread.IsBackground = true;
|
m_packageThread.Start();
|
isStopTreading = false;
|
Debug.unityLogger.logEnabled = true;
|
Debug.Log("[ClientSocket][OnConnectSuccess] 连接成功,启动接收线程");
|
if (m_packageThread != null)
|
{
|
Debug.LogWarning("[ClientSocket][OnConnectSuccess] m_packageThread已存在,先Abort");
|
m_packageThread.Abort();
|
m_packageThread = null;
|
}
|
|
m_LastPackageTime = DateTime.Now;
|
m_packageThread = new Thread(new ThreadStart(ReceiveInfo)); // 启动线程接收信息
|
m_packageThread.IsBackground = true;
|
m_packageThread.Start();
|
isStopTreading = false;
|
}
|
|
/// <summary>
|
/// 接收信息
|
/// </summary>
|
private void ReceiveInfo()
|
{
|
while (!isStopTreading)
|
{
|
try
|
{
|
var shutdown = false;
|
if (!m_Socket.Connected)
|
{
|
shutdown = true;
|
}
|
|
if (!shutdown)
|
{
|
var dataLength = m_Socket.Receive(bufferBytes);
|
if (dataLength <= 0)
|
{
|
shutdown = true;
|
}
|
else
|
{
|
getBytesTotal += dataLength;
|
var bytes = new byte[dataLength];
|
Array.Copy(bufferBytes, 0, bytes, 0, dataLength);
|
ReadInfo(bytes);
|
}
|
}
|
|
if (shutdown)
|
{
|
isStopTreading = true;
|
m_Socket.Shutdown(SocketShutdown.Both);
|
m_Socket.Close();
|
}
|
}
|
catch (Exception e)
|
{
|
Debug.Log(e);
|
}
|
}
|
Debug.unityLogger.logEnabled = true;
|
Debug.Log("[ClientSocket][ReceiveInfo] 接收线程启动");
|
while (!isStopTreading)
|
{
|
try
|
{
|
var shutdown = false;
|
if (!m_Socket.Connected)
|
{
|
Debug.LogWarning("[ClientSocket][ReceiveInfo] m_Socket 已断开");
|
shutdown = true;
|
}
|
|
if (!shutdown)
|
{
|
var dataLength = m_Socket.Receive(bufferBytes);
|
Debug.Log($"[ClientSocket][ReceiveInfo] 收到数据长度: {dataLength}");
|
if (dataLength <= 0)
|
{
|
Debug.LogWarning("[ClientSocket][ReceiveInfo] dataLength <= 0,准备断开");
|
shutdown = true;
|
}
|
else
|
{
|
getBytesTotal += dataLength;
|
var bytes = new byte[dataLength];
|
Array.Copy(bufferBytes, 0, bytes, 0, dataLength);
|
ReadInfo(bytes);
|
}
|
}
|
|
if (shutdown)
|
{
|
Debug.LogWarning("[ClientSocket][ReceiveInfo] shutdown=true,关闭Socket");
|
isStopTreading = true;
|
m_Socket.Shutdown(SocketShutdown.Both);
|
m_Socket.Close();
|
}
|
}
|
catch (Exception e)
|
{
|
Debug.LogError($"[ClientSocket][ReceiveInfo] 异常: {e}");
|
}
|
}
|
Debug.Log("[ClientSocket][ReceiveInfo] 接收线程退出");
|
|
}
|
|
/// <summary>
|
/// 解析数据包: FFCC+封包长度+封包(封包头+数据)结构体内容
|
/// </summary>
|
/// <param name="vBytes"></param>
|
private void ReadInfo(byte[] vBytes)
|
{
|
try
|
{
|
byte[] fixBytes = vBytes;
|
// 如果存在留包,则并包
|
if (fragmentBytes != null && fragmentBytes.Length > 0)
|
{
|
Array.Resize(ref fixBytes, vBytes.Length + fragmentBytes.Length);
|
Debug.Log($"[ClientSocket][ReadInfo] 存在fragmentBytes, 长度: {fragmentBytes.Length}");
|
Array.Copy(fragmentBytes, 0, fixBytes, 0, fragmentBytes.Length);
|
Array.Copy(vBytes, 0, fixBytes, fragmentBytes.Length, vBytes.Length);
|
}
|
|
fragmentBytes = null; // 清理掉留包
|
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) // 未符合包的最低限度字节量, 留包
|
{
|
fragmentBytes = new byte[vLeavingLeng];
|
Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
|
break;
|
}
|
vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
|
if (vBodyLeng > vLeavingLeng - 6)// 未完整的包则留包
|
{
|
fragmentBytes = new byte[vLeavingLeng];
|
Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, 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)
|
{
|
// if (Launch.Instance.EnableNetLog)
|
// {
|
// Debug.LogFormat("收包:{0}", vNetpack.GetType().Name);
|
// }
|
m_LastPackageTime = DateTime.Now;
|
GameNetSystem.Instance.PushPackage(vNetpack, this.socketType);
|
isRegist = true;
|
}
|
}
|
|
|
vReadIndex += 6 + vBodyLeng;
|
|
// 未注册封包处理
|
if (!isRegist)
|
{
|
#if UNITY_EDITOR
|
PackageRegedit.TransPack(socketType, cmd, vPackBytes);
|
#endif
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
Debug.LogErrorFormat("收包异常:{0}", ex);
|
}
|
|
}
|
|
// 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)
|
{
|
sendQueue.Enqueue(bytes);
|
}
|
else
|
{
|
m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
|
}
|
}
|
catch
|
{
|
Debug.LogError("网络数据包发送异常");
|
}
|
}
|
|
/// <summary>
|
/// 发送完成的回调
|
/// </summary>
|
/// <param name="vAsyncSend"></param>
|
private void SendInfoCallBack(IAsyncResult vAsyncSend)
|
{
|
try
|
{
|
if (sendQueue.Count > 0)
|
{
|
var bytes = sendQueue.Dequeue();
|
m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
|
}
|
}
|
catch (Exception ex)
|
{
|
Debug.Log(ex);
|
}
|
}
|
|
public void DispatchMessageQueue()
|
{
|
// TCP不需要轮询
|
}
|
|
#else
|
// ==================== WebSocket 实现(WebGL平台)====================
|
|
public async void Connect(string _ip, int _port, Action<bool> _onConnected)
|
{
|
Debug.unityLogger.logEnabled = true;
|
ip = _ip;
|
port = _port;
|
onConnected = _onConnected;
|
|
var scheme = Application.absoluteURL.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ? "wss" : "ws";
|
webSocketUrl = $"{scheme}://{_ip}:{_port}";
|
webSocketOpened = false;
|
Debug.Log($"[ClientSocket-WebSocket] 开始连接: {webSocketUrl}, pageUrl={Application.absoluteURL}");
|
|
try
|
{
|
webSocket = new WebSocket(webSocketUrl);
|
|
// 注册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()
|
{
|
webSocketOpened = true;
|
Debug.Log($"[ClientSocket-WebSocket] 连接成功: {webSocketUrl}");
|
m_LastPackageTime = DateTime.Now;
|
|
if (onConnected != null)
|
{
|
onConnected(true);
|
onConnected = null;
|
}
|
}
|
|
private void OnWebSocketMessage(byte[] data)
|
{
|
try
|
{
|
getBytesTotal += data.Length;
|
|
byte[] fixBytes = data;
|
// TCP-to-WS网关按TCP缓冲区大小拆分,需跨消息重组(与TCP ReadInfo逻辑一致)
|
if (fragmentBytes != null && fragmentBytes.Length > 0)
|
{
|
fixBytes = new byte[fragmentBytes.Length + data.Length];
|
Array.Copy(fragmentBytes, 0, fixBytes, 0, fragmentBytes.Length);
|
Array.Copy(data, 0, fixBytes, fragmentBytes.Length, data.Length);
|
}
|
fragmentBytes = null;
|
|
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)
|
{
|
fragmentBytes = new byte[vLeavingLeng];
|
Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
|
break;
|
}
|
|
// 校验FFCC包头,防止数据错位
|
if (fixBytes[vReadIndex] != 0xFF || fixBytes[vReadIndex + 1] != 0xCC)
|
{
|
Debug.LogError($"[ClientSocket-WebSocket] FFCC包头异常: {fixBytes[vReadIndex]:X2} {fixBytes[vReadIndex + 1]:X2}, 丢弃剩余 {vLeavingLeng} 字节");
|
fragmentBytes = null;
|
break;
|
}
|
|
vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
|
if (vBodyLeng <= 0)
|
{
|
Debug.LogError($"[ClientSocket-WebSocket] 包体长度非法: {vBodyLeng}, 丢弃");
|
fragmentBytes = null;
|
break;
|
}
|
if (vBodyLeng > vLeavingLeng - 6)
|
{
|
fragmentBytes = new byte[vLeavingLeng];
|
Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, 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}");
|
if (!webSocketOpened && onConnected != null)
|
{
|
onConnected(false);
|
onConnected = null;
|
}
|
}
|
|
private void OnWebSocketClose(WebSocketCloseCode code)
|
{
|
Debug.LogError($"[ClientSocket-WebSocket] 连接关闭: code={code}, url={webSocketUrl}, opened={webSocketOpened}");
|
if (!webSocketOpened && onConnected != null)
|
{
|
onConnected(false);
|
onConnected = null;
|
}
|
OnDisconnected?.Invoke();
|
}
|
|
public async void CloseConnect()
|
{
|
Debug.Log("[ClientSocket-WebSocket] ==== CloseConnect\n" + System.Environment.StackTrace);
|
fragmentBytes = null;
|
|
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
|
|
// ==================== 统一的公共接口(两个平台通用)====================
|
|
/// <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
|
}
|