using System; using UnityEngine; using BestHTTP.SocketIO; using Newtonsoft.Json; namespace JC.SocketIO { public class SocketIOClient : MonoBehaviour { private SocketManager _manager; private Socket _socket; private string _uri; public virtual void OnDestroy() { if (_manager != null) { _manager.Close(); } } public void connectServer(string uri) { _uri = uri; _manager = new SocketManager(new System.Uri(_uri)); _manager.Options.AutoConnect = true; //自动打开 _manager.Options.Reconnection = true; //自动重连 _socket = _manager.Socket; _socket.On(SocketIOEventTypes.Error, delegate(Socket socket, Packet packet, object[] args) { if (!isValid) { try { onMiss(); } catch (Exception e) { Debug.LogError(e.Message); } } }); _socket.On(SocketIOEventTypes.Disconnect, delegate(Socket socket, Packet packet, object[] args) { if (isValid) { isValid = false; try { onDestroy(); } catch (Exception e) { Debug.LogError(e.Message); } } }); _socket.On("call", delegate(Socket socket, Packet packet, object[] args) { string str = packet.Payload; int si = str.IndexOf("{"); int ei = str.LastIndexOf("]"); str = str.Substring(si, ei - si); invoke(JsonConvert.DeserializeObject(str)); }); } public void reconnectServer() { if (_manager != null) { _manager.Close(); } connectServer(_uri); } [NonSerialized] public bool isValid; [NonSerialized] public bool loaded; public virtual void onLoad() {} public virtual void onReload() {} public virtual void onDestroy() {} public virtual void onMiss() {} public void call(string func, params object[] args) { if (!isValid) return; DataPack dataPack = new DataPack(); dataPack.type = 1; dataPack.func = func; dataPack.args = Utility.FormatArgs(args); _socket.Emit("call", JsonConvert.SerializeObject(dataPack)); } private void invoke(DataPack dataPack) { if (dataPack.type == 0) { if (dataPack.func == "onLoad") { isValid = true; try { if (loaded) { onReload(); } else { onLoad(); } } catch (Exception e) { Debug.LogError(e.Message); } loaded = true; } } else if (dataPack.type == 1) { System.Reflection.MethodInfo method = this.GetType().GetMethod(dataPack.func); Utility.FormatArgsType(dataPack.args, method.GetParameters()); method.Invoke(this, dataPack.args); } } class DataPack { public int type; public string func; public object[] args; } class Utility { public static long GetTimestamp() { TimeSpan ts = DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1); return (long)ts.TotalMilliseconds; } public static object[] FormatArgs(object[] args) { object[] newArgs = new object[args.Length]; for (int i = 0; i < args.Length; i++) { object arg = args[i]; if (!IsBaseType(arg.GetType())) { newArgs[i] = JsonConvert.SerializeObject(arg); } else { newArgs[i] = arg; } } return newArgs; } public static void FormatArgsType(object[] args, System.Reflection.ParameterInfo[] parameters) { int i = 0; foreach (var param in parameters) { Type type = param.ParameterType; if (IsBaseType(type)) { args[i] = Convert.ChangeType(args[i], type); } else { args[i] = JsonConvert.DeserializeObject((string) args[i], type); } i++; } } public static bool IsBaseType(Type type) { if (typeof(System.Int32).Equals(type)) return true; if (typeof(System.Int64).Equals(type)) return true; if (typeof(System.Single).Equals(type)) return true; if (typeof(System.Double).Equals(type)) return true; if (typeof(System.String).Equals(type)) return true; if (typeof(System.Boolean).Equals(type)) return true; return false; } } } }