using UnityEngine; using System.Net.Sockets; using System; using System.Linq; using System.IO; using XFramework.NetOuter; using UnityEngine.Events; using System.Collections.Generic; public class TcpClient { ProtocolBase protocol=new ProtocolByte(); string path=""; // public string serverMess=""; public Socket socket; public const int bufferSize=16384;//最大可缓存16kb 的数据 int bufferCount = 0; byte[] readBuffer = new byte[bufferSize]; byte[] lenbytes=new byte[sizeof(Int32)]; Int32 msgLength; //string GetConnState; private MsgDistribution msgDis = new MsgDistribution(); string address=""; int port=0; float timer; float heatBeatTime=5; /// /// 连接状态变化 /// event UnityAction ConnectChanged; Queue changedQueue = new Queue();//记录支线程 网络状态变化 public TcpClient(UnityAction ConnectChanged = null) { this.ConnectChanged += ConnectChanged; ReadConfig(); AddListener(); ConnectServer(); } // Mono类代为调用 public void ExtractingMsg() { msgDis.Distribution(); timer += Time.deltaTime; if (timer > heatBeatTime) { HeatBeat(); timer = 0; } if (changedQueue.Count > 0) { ConnectChanged?.Invoke(changedQueue.Dequeue()); } } //连接到服务器 private void ConnectServer() { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.BeginConnect(address, port, ReceiveConn, null); //Debug.Log($"尝试建立连接{address}:{port}"); } private void ReceiveConn(IAsyncResult ar) { if (socket.Connected) { socket.BeginReceive(readBuffer, 0, bufferSize, SocketFlags.None, ReceiveCb, null); changedQueue.Enqueue(true); } } //读取配置文件获取IP和端口 private void ReadConfig() { path = Application.streamingAssetsPath + "/TcpConfig/ServerAdress.txt"; if (File.Exists(path)) { string[] config = File.ReadAllText(path, System.Text.Encoding.UTF8).Split(','); if (config.Length >= 2) { address = config[0].Trim(); port = int.Parse(config[1].Trim()); } else { Debug.Log("config is error"); } } } //添加监听消息事件 void AddListener() { msgDis.AddListener(NetMsgName.LoginResult.ToString(), new TCPLoginResultExcute()); msgDis.AddListener(NetMsgName.Subject.ToString(), new TCPSubExcute()); msgDis.AddListener(NetMsgName.AdjustingToStu.ToString(), new TCPAdjustingToStuExcute()); msgDis.AddListener(NetMsgName.AddOrRmoveTufa.ToString(), new TCPAddOrRmoveTufaExcute()); msgDis.AddListener(NetMsgName.AppraiseResult.ToString(), new TCPAppraiseResultExcute()); msgDis.AddListener(NetMsgName.GroupUserBreak.ToString(), new UserDiscExcute());//掉线处理逻辑 } //接收信息的回调 private void ReceiveCb(IAsyncResult ar) { try { int count = socket.EndReceive(ar); bufferCount += count; ProcessData(); socket.BeginReceive(readBuffer, bufferCount, bufferSize- bufferCount, SocketFlags.None, ReceiveCb, null); } catch (Exception e) { Debug.Log(e.Message+"接收消息失败,断开连接"); changedQueue.Enqueue(false); socket.Close(); } } //验证信息完整程度并删除处理完成的信息 private void ProcessData() { if (bufferCount < sizeof(Int32)) return; Array.Copy(readBuffer,lenbytes,sizeof(Int32)); msgLength = BitConverter.ToInt32(lenbytes,0); if (msgLength < 0) { Debug.Log("ReadBuffer解析数据长度解析有误"); return; } if (msgLength > bufferSize) { Debug.Log("ReadBuffer数据长度超出缓存空间"); return; } if (bufferCount < sizeof(Int32) + msgLength) return; ProtocolByte proto = (ProtocolByte)protocol.Decode(readBuffer, sizeof(Int32), msgLength); //HandleMsg(proto); ExcuteParam excute = new ExcuteParam(address,proto.GetProtocolName(), proto); msgDis.Enqueue(excute); int count = bufferCount - sizeof(Int32) - msgLength; Array.Copy(readBuffer,sizeof(Int32)+msgLength,readBuffer,0,count); bufferCount = count; if (bufferCount > 0) ProcessData(); } //发送位置信息 //发送传输协议到服务器 public void Send(ProtocolBase proto) { byte[] bytes = proto.Encode(); byte[] length = BitConverter.GetBytes(bytes.Length); byte[] sendBytes = length.Concat(bytes).ToArray(); try { socket.Send(sendBytes); } catch (Exception) { //Debug.Log("接收消息失败,断开连接"); socket.Close(); } } //心跳 void HeatBeat() { //Debug.Log(connIsRight); if (socket.Connected) { ProtocolByte protoco = new ProtocolByte(); protoco.AddString("HeatBeat"); Send(protoco); } else { ConnectServer(); } } //关闭连接 public bool Close() { try { socket.Close(); ConnectChanged?.Invoke(false); return true; } catch (Exception e) { Debug.Log("关闭失败:"+e.Message); return false; } } }