/// <summary> /// 压缩文件,参数是输入文件路径和输出文件路径。 /// </summary> /// <param name="sourceFile">输入文件路径</param> /// <param name="destinationFile">输出文件路径</param> public static void CompressFile(string sourceFile, string destinationFile) { // make sure the source file is there if (File.Exists(sourceFile) == false) { throw new FileNotFoundException(); } // Create the streams and byte arrays needed byte[] buffer = null; FileStream sourceStream = null; FileStream destinationStream = null; GZipStream compressedStream = null; try { // Read the bytes from the source file into a byte array sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read); // Read the source stream values into the buffer buffer = new byte[sourceStream.Length]; int checkCounter = sourceStream.Read(buffer, 0, buffer.Length); if (checkCounter != buffer.Length) { throw new ApplicationException(); } // Open the FileStream to write to destinationStream = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.Write); // Create a compression stream pointing to the destiantion stream compressedStream = new GZipStream(destinationStream, CompressionMode.Compress, true); // Now write the compressed data to the destination file compressedStream.Write(buffer, 0, buffer.Length); } catch (ApplicationException e) { DxDebug.LogWarning("GZip.CompressFile():异常:" + e.Message); } finally { // Make sure we allways close all streams if (sourceStream != null) { sourceStream.Close(); } if (compressedStream != null) { compressedStream.Close(); } if (destinationStream != null) { destinationStream.Close(); } } }
/// <summary> /// 压缩一段数据,这个数据长度不能过大,最好在1M以内 /// </summary> /// <param name="sourceData">用于存储压缩字节的数组</param> /// <param name="offset">数组中开始读取的位置</param> /// <param name="count">压缩的字节数</param> /// <returns></returns> public static byte[] CompressBytes(byte[] sourceData, int offset, int count) { if (sourceData == null) { return(null); } MemoryStream destinationStream = new MemoryStream(); GZipStream compressedStream = new GZipStream(destinationStream, CompressionMode.Compress); try { compressedStream.Write(sourceData, offset, count); compressedStream.Close(); byte[] CompressedData = destinationStream.ToArray(); destinationStream.Close(); return(CompressedData); } catch (Exception e) { DxDebug.LogWarning("GZip.CompressBytes():异常:" + e.Message); } finally { // Make sure we allways close all streams if (destinationStream != null) { destinationStream.Close(); } } return(null); }
/// <summary> /// 添加一个token /// </summary> /// <param name="token"></param> internal Token AddToken(Token token) { lock (this._lockDict) { token.ID = _curID; _dictToken.Add(token.ID, token); //递增ID计数,额,不过上面已经加锁了 Interlocked.Increment(ref _curID); _isDictEqualArr = false; //标记当前字典和列表已经不一致了 } if (EventAddToken != null) //事件 { try { EventAddToken(token.ID); } catch (Exception e) { DxDebug.LogWarning("TokenManager.AddToken():执行事件EventAddToken异常!" + e.Message); } } DxDebug.LogConsole(String.Format("TokenManager.AddToken():添加了一个客户端. 当前服务器上有{0}个客户端; ip:{1}", _dictToken.Count, token.IP)); return(token); }
private void Dispose(bool disposing) { if (disposed) { return; } if (disposing) { // 清理托管资源 } // 清理非托管资源 try { if (_timer != null) { _timer.Dispose(); } } catch (Exception e) { DxDebug.LogWarning("ServerTimer.Dispose():异常_timer.Dispose()" + e.Message); } //让类型知道自己已经被释放 disposed = true; }
/// <summary> /// 发送一条数据,有起始和长度控制 /// </summary> /// <param name="data">要发送的数据</param> /// <param name="offset">数据的起始位置</param> /// <param name="count">数据的长度</param> public void Send(byte[] data, int offset, int count) { if (data == null) { DxDebug.LogWarning("DNClient.Send(data,offset,count):要发送的数据为null!"); } try { _packet2.AddSend(data, offset, count);//添加这条消息到打包器 //进行数据的预打包,然后不拷贝 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Send); } else { msg.Reset(NetWorkMsg.Tpye.C_Send); } AddMessage(msg); } catch (Exception e) { DxDebug.LogWarning("DNClient.Send(p1,p2,p3):异常 " + e.Message); } }
/// <summary> /// 添加一个工作任务到消息队列,提供给这些线程来处理 /// </summary> /// <param name="msg"></param> public void AddMessage(IWorkMsg msg) { try { if (_msgQueue.EnqueueMaxLimit(msg)) { if (_curSemCount < 1)//如果当前的信号量剩余不多的时候 { Interlocked.Increment(ref _curSemCount); _msgSemaphore.Release();// 释放信号量 } } else { DxDebug.LogWarning("WorkThread.AddMessage():大于工作线程的能力了,丢弃了一条消息!"); } if (_msgQueuePeakLength < _msgQueue.Count) { _msgQueuePeakLength = _msgQueue.Count;//记录当前的峰值长度 } } catch (SemaphoreFullException) { DxDebug.LogError("WorkThread.AddMessage():大于工作线程的能力了:"); throw; } catch (Exception e) { DxDebug.LogError("WorkThread.AddMessage():异常:" + e.Message); throw; } }
private void DoClose() { try { IsInited = false; DxDebug.LogConsole("DNClient.DoClose():开始释放资源 "); _disposed = true; // 清理托管资源 _msgQueue.Clear(); _msgPool.Clear(); _msgQueue = null; _msgPool = null; // 清理非托管资源 _msgSemaphore.Close(); _msgSemaphore = null; Interlocked.Exchange(ref _curSemCount, 0); if (_socketClient != null) { _socketClient.Dispose(); _socketClient = null; } IsConnecting = false; } catch (Exception e) { DxDebug.LogWarning("DNClient.DoClose():异常: " + e.Message); } }
private void OnSend() { if (_isDebugLog) { DxDebug.LogConsole("-----------EventHandler.OnSend():进入OnSend回调!"); } Interlocked.Decrement(ref _snedingCount); if (_packet2.SendMsgCount > 0) //如果待发送队列里有消息,不需要再判断_snedingCount < MAX_SENDING_DATA,直接开始下一次发送 { NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Send); } else { msg.Reset(NetWorkMsg.Tpye.C_Send); } AddMessage(msg); } else { } }
private void Dispose(bool disposing) { DxDebug.LogConsole(String.Format("TokenManager.Dispose():进入了Dispose!")); if (disposed) { return; } if (disposing) { // 清理托管资源 EventAddToken = null; EventDeleteToken = null; //断开所有 DeleteAllToken(); _dictToken.Clear(); _dictToken = null; _arrToken = null; } // 清理非托管资源 //让类型知道自己已经被释放 disposed = true; }
private void DoReceive() { try { //不再做心跳包处理,直接发出事件 LastMsgReceTickTime = DateTime.Now.Ticks; //接收数据事件 if (EventReceData != null) { try { EventReceData(this);//发出事件:接收到了数据 } catch (Exception e) { DxDebug.LogWarning("DNClient.DoReceive():执行外部事件EventReceData 异常: " + e.Message); } } //DxDebug.Log("-----------数据解包完成,数据条数: " + findPacketResult.data.Length); } catch (Exception e) { DxDebug.LogWarning("DNClient.DoReceive():异常: " + e.Message); } }
private void DoStart(NetWorkMsg msg) { try { DxDebug.LogConsole("DNServer.DoStart():工作线程开始执行DoStart()..."); if (_socketListener != null) { DxDebug.Log(" DNServer.DoStart():_socketListener.Dispose();"); _socketListener.Dispose(); } DxDebug.Log("DNServer.DoStart():_socketListener = new SocketListener(CONNECTIONS_BUFFER_SIZE);"); _socketListener = new SocketListener(this, CONNECTIONS_BUFFER_SIZE); DxDebug.Log("DNServer.DoStart():_socketListener.EventAccept += OnAccept;"); _socketListener.EventAccept += OnAccept; _socketListener.EventReceive += OnReceive; _socketListener.EventSend += OnSend; _socketListener.EventError += OnTokenError; DxDebug.Log("DNServer.DoStart(): _socketListener.Start(" + _port + ");"); _socketListener.Start(msg.text1, _port); DxDebug.LogConsole("DNServer.DoStart()执行完毕!"); } catch (Exception e) { DxDebug.LogWarning("DNServer.DoStart():异常 " + e.Message); } }
/// <summary> /// 启动服务器,会开启工作线程然后释放一个DoStart信号量。 /// </summary> /// <param name="port">端口号</param> /// <param name="threadCount">服务器使用的处理线程数量</param> /// <param name="hostName">服务器的主机IP,一般使用Any表示所有的可能IP</param> public void Start(int port, int threadCount = 1, string hostName = "Any") { try { DxDebug.LogConsole("DNServer.Start():服务器工作线程数 " + threadCount); if (disposed) { TokenManager.GetInst().Clear(); _msgQueue = new DQueue <NetWorkMsg>(MSG_QUEUE_CAPACITY); _msgSemaphore = new Semaphore(0, MSG_QUEUE_CAPACITY); _workThread = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { _workThread[i] = new Thread(DoWork); _workThread[i].IsBackground = true; //工作线程的优先级(影响不大) _workThread[i].Priority = ThreadPriority.Highest; _workThread[i].Name = "SeverThread " + i; _workThread[i].Start(); //启动线程 } disposed = false; } _port = port; NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Start, null); msg.text1 = hostName; AddMessage(msg); } catch (Exception e) { DxDebug.LogError("DNServer.Start():异常 " + e.Message); } }
/// <summary> /// 开始一个接收 /// </summary> private void PrepareReceive() { try { //这里是需要的,否则在断线之后仍然可能不停的接收 if (!_clientSocket.Connected) //如果当前没有连接上,就不接收了 { return; } #if !NEW_EVENT_AEGS _receiveArgs.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length); #else SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs(); receiveArgs.UserToken = this.clientSocket; receiveArgs.RemoteEndPoint = this.hostEndPoint; byte[] receiveBuffer = new byte[2048]; //接收buffer大小为2048; receiveArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); receiveArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnReceive); #endif if (!_clientSocket.ReceiveAsync(_receiveArgs))//开始接收 { ProcessReceive(this, _receiveArgs); } _receTime.WaitStart(); } catch (Exception e) { DxDebug.LogWarning("SocketClient.PrepareReceive() 开始异步接收错误:" + e.Message); //这里捕获过的异常有: // Thread creation failed. } }
/// <summary> /// 根据期望大小获得一个buffer. /// autoSetValidLength为true则默认设置validLength为期望大小,否则设置为0. /// </summary> /// <param name="size">期望大小</param> /// <param name="autoSetValidLength">是否validLength会自动标记为size</param> /// <returns></returns> public ByteBuffer GetBuffer(long size, bool autoSetValidLength = false) { ByteBuffer bbf = null; if (size > maxBlockSize) { ByteBufferPool.countNew++; DxDebug.LogConsole("ByteBufferPools.GetBuffer():申请了一块过大的内存,size=" + size); //这个内存块太了,所以就不作缓存了 bbf = new ByteBuffer(size); } else { ByteBufferPool bbPool = ChoosePool(size); bbf = bbPool.GetBuffer((int)size); } if (autoSetValidLength) { bbf.validLength = (int)size; } else { bbf.validLength = 0; } return(bbf); }
private void ProcessReceive(object sender, SocketAsyncEventArgs e) { _receTime.WorkStart(); try { //_areReceiveDone.Set();//设置信号量(但是目前压根没用到) if (e.SocketError != SocketError.Success) { this.ProcessError(e); } if (e.BytesTransferred > 0) //有可能会出现接收到的数据长度为0的情形,如当服务器关闭连接的时候 { //写入当前接收的数据 int msgCount = _packet2.AddRece(e.Buffer, e.Offset, e.BytesTransferred); //如果确实收到了一条消息 if (msgCount > 0 && EventReceive != null) //执行事件 { EventReceive(); } } else { this.ProcessError(e); } PrepareReceive(); //开始下一个接收 } catch (Exception ex) { DxDebug.LogWarning("SocketClient:ProcessReceive():" + ex.Message); } }
/// <summary> /// 发生错误后就关闭连接 /// </summary> /// <param name="e"></param> private void ProcessError(SocketAsyncEventArgs e) { DxDebug.LogWarning("SocketClient.ProcessError():进入了ProcessError. ErroType:" + e.SocketError); //显示下接收的信息 Socket s = e.UserToken as Socket; //使用传递的Token if (s.Connected) { try { DxDebug.LogConsole("SocketClient.ProcessError():调用Shutdown()关闭连接"); s.Shutdown(SocketShutdown.Both); } catch (Exception ex) { DxDebug.LogWarning("SocketClient.ProcessError() :Shutdown()异常 " + ex.Message); } finally { if (s.Connected) { s.Close(); DxDebug.LogWarning("SocketClient.ProcessError() :调用Close()关闭了连接");//这里是否必须要关闭待定 } } } //产生错误事件,这是一个很重要的事件,处理服务器连接断开等 if (EventError != null) { EventError(); } }
/// <summary> /// 删除一个token,会自动关闭连接。会产生事件 /// </summary> /// <param name="id">根据ID删除已个Token</param> public void DeleteToken(int id) { CloseToken(id, TokenErrorType.UserDelete);//先关闭 lock (this._lockDict) { if (_dictToken.ContainsKey(id)) { _dictToken.Remove(id); _isDictEqualArr = false;//标记当前字典和数组已经不一致了 } else { return; } } if (EventDeleteToken != null)//事件 { try { EventDeleteToken(id, TokenErrorType.UserDelete);//这个是外部的调用删除 } catch (Exception e) { DxDebug.LogWarning("TokenManager.DeleteToken():执行事件EventDeleteToken异常!" + e.Message); } } DxDebug.LogConsole(String.Format("TokenManager.DeleteToken():关闭了一个客户端. 还有{0}个客户端,原因{1}", _dictToken.Count, TokenErrorType.UserDelete.ToString())); }
private void ProcessConnect(object sender, SocketAsyncEventArgs e) { try { //这种回调是新开了一个线程执行的 _areConnectDone.Set(); if (IsConnected) { PrepareReceive(); //自动开始一个接收 } else { DxDebug.LogWarning("SocketClient.ProcessConnect():没能自动开始接收 IsConnected = " + IsConnected); } if (EventConnect != null) //执行事件 { EventConnect(); } } catch (Exception ex) { DxDebug.LogWarning("SocketClient.ProcessConnect():异常:" + ex.Message); } }
/// <summary> /// 线程函数,向所有Token发送他们的待发送数据 /// </summary> /// <param name="msg"></param> private void DoSendAll(NetWorkMsg msg) { try { Token[] tokens = TokenManager.GetInstance().GetAllToken(); if (tokens == null) { return; } for (int i = 0; i < tokens.Length; i++) { Token token = tokens[i]; //DxDebug.Log("DoSend : ID号 " + token.ID + " 当前的SendingCount " + token.SendingCount); if (token.SendingCount < MAX_TOKEN_SENDING_COUNT) { int msgCount = token.SendQueueCount; byte[] data = token.PackSendData(_packet); //打包发送 if (data != null) { Interlocked.Add(ref Status.CountSend, msgCount); //状态统计发送递增 Interlocked.Add(ref Status.CountSendBytes, data.Length); //状态统计递增发送数据长度 _socketListener.Send(token, data); } } else //如果当前正在发送,那么这次发送完成之后,会自动的开始下一次发送:OnSend()函数 { } } } catch (Exception e) { DxDebug.LogWarning("DNServer.DoSendAll():异常 " + e.Message); } }
/// <summary> /// 定时器函数 /// </summary> /// <param name="state"></param> private void OnTimerTick(object state) { try { //如果自动心跳包功能打开了 if (Config.IsAutoHeartbeat == true) { CheckOffLineAndSend(); } //执行事件 if (EventOnTimer != null) { try { EventOnTimer(); } catch (Exception e) { DxDebug.LogWarning("ServerTimer.OnTimerTick():执行EventOnTimer事件异常:" + e.Message);; } } } catch (Exception e) { DxDebug.LogWarning("ServerTimer.OnTimerTick():异常:" + e.Message); } }
/// <summary> /// 发送一条数据 /// </summary> /// <param name="data">要发送的整个数据</param> public void Send(byte[] data) { if (data == null) { DxDebug.LogWarning("DNClient.Send():要发送的数据为null!"); } try { _packet2.AddSend(data, 0, data.Length);//添加这条消息到打包器 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Send); } else { msg.Reset(NetWorkMsg.Tpye.C_Send); } AddMessage(msg); } catch (Exception e) { DxDebug.LogWarning("DNClient.Send():异常 " + e.Message); } }
/// <summary> /// Dispose,这个对象的Close()函数会调用该函数 /// </summary> public void Dispose() { if (_workThread != null) { DxDebug.Log("DNClient.Dispose():_threadTest.IsAlive 为:" + _workThread.IsAlive); } Dispose(true); }
/// <summary> /// 构造函数 /// </summary> public TokenManager() { if (_instance != null) { DxDebug.LogWarning("TokenManager是个单例,被多次调用构造函数"); //this.Dispose(); //_instance = null; } }
private void DoWork() { DxDebug.LogConsole("DNServer.DoWork():服务器线程启动!"); while (true) { _msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); while (true) { _cpuTime.WorkStart(); //时间分析计时 #if Multitask NetWorkMsg msg1 = _msgQueue.Dequeue(); NetWorkMsg msg2 = _msgQueue.Dequeue(); if (msg1 == null && msg2 == null) { break; } else if (msg1 != null && msg2 != null)//取到了两条消息 { //再消耗一条信号量 //_msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); Parallel.Invoke(delegate() { ProcessMsg(msg1); }, delegate() { ProcessMsg(msg2); }); } else if (msg1 != null && msg2 == null) { //只有一条消息,就直接执行 ProcessMsg(msg1); } else if (msg1 == null && msg2 != null) { //只有一条消息,就直接执行 ProcessMsg(msg2); } #else NetWorkMsg msg = _msgQueue.Dequeue(); if (msg == null) //直到消息取尽之前都不停的处理 { break; } float waitTime = (DateTime.Now.Ticks - msg.timeTickCreat) / 10000;//毫秒 if (waitTime > _warringWaitTime) { _warringWaitTime += 500; DxDebug.LogWarning("DNServer.DoWork():NetWorkMsg等待处理时间过长!waitTime:" + waitTime); } else if ((_warringWaitTime - waitTime) > 500) { _warringWaitTime -= 500; } ProcessMsg(msg); #endif _cpuTime.WaitStart(); //时间分析计时 } } }
private void DoConnect() { try { //DxDebug.LogConsole("DNClient.DoConnect():执行Connect..."); //标记正在连接 IsConnecting = true; Interlocked.Exchange(ref _snedingCount, 0); this.Clear();//清空数据 if (_socketClient != null) { //DxDebug.LogConsole("DNClient.DoConnect():断开原先连接!"); _socketClient.Disconnect(); _socketClient.Bind(_host, _port);//绑定新ip _socketClient.Clear(); DxDebug.LogConsole("DNClient.DoConnect():-----------正在连接..."); _socketClient.Connect(); DxDebug.LogConsole("DNClient.DoConnect():-----------连接服务器成功!" + _host + ":" + _port); } else { _socketClient = new SocketClient(_host, _port, _packet2); if (_socketClient == null) { DxDebug.LogError("DNClient.DoConnect():-----------连接服务器失败!_socketClient对象未能创建成功。"); return; } _socketClient.EventReceive += OnReceive; //加入接收事件 _socketClient.EventSend += OnSend; //加入发送事件 _socketClient.EventError += OnError; //加入错误事件 DxDebug.LogConsole("DNClient.DoConnect():-----------正在连接..."); _socketClient.Connect(); DxDebug.LogConsole("DNClient.DoConnect():-----------连接服务器成功!" + _host + ":" + _port); } if (EventConnectSuccess != null) { try { EventConnectSuccess(this); }//事件类型:ConnectError catch (Exception e) { DxDebug.LogError("DNClient.DoConnect():执行EventError事件异常:" + e.Message); } } } catch (Exception e) { DxDebug.LogError("DNClient.DoConnect():-----------连接服务器失败!: " + e.Message); if (EventError != null) { try { EventError(this, EventType.ConnectError, e); }//事件类型:ConnectError catch (Exception e2) { DxDebug.LogError("DNClient.DoConnect():执行EventError事件异常:" + e2.Message); } } } //标记已经结束了连接 IsConnecting = false; }
/// <summary> /// 定时器函数 /// </summary> /// <param name="state"></param> private void OnTimerTick(object state) { DNClient client = DNClient.GetInstance(); if (Config.IsAutoHeartbeat && client.IsConnected) { float time = (DateTime.Now.Ticks - client.LastMsgSendTickTime) / 10000; if (time > Config.HeartBeatSendTime)//如果时间已经超过了那么就发送心跳包 { //发送一次心跳包 SendHeartBeat(); } } if (Config.IsAutoHeartbeat && client.IsConnected) { //如果15s没有收到心跳包 float time = (DateTime.Now.Ticks - client.LastMsgReceTickTime) / 10000; if (time > Config.HeartBeatCheckTime) { DxDebug.LogWarning("ClientTimer.OnTimerTick():长时间没有收到心跳包,判断可能已经掉线!"); client.Disconnect();//关闭连接 } } //执行事件 if (EventOnTimer != null) { try { EventOnTimer(); } catch (Exception e) { DxDebug.LogWarning("ClientTimer.OnTimerTick():执行EventOnTimer事件异常:" + e.Message); } } //执行3秒事件 if (EventOnTimer3S != null) { _count3S += KICK_TIME; if (_count3S >= 3 * 1000) //20秒 { _count3S = 0; try { EventOnTimer3S(); } catch (Exception e) { DxDebug.LogWarning("ClientTimer.OnTimerTick():执行EventOnTimer3S事件异常:" + e.Message);; } } } }
/// <summary> /// 解包当前已经接收到的原始数据,结果存放进了已接收消息队列, 返回true如果接收到了消息. /// </summary> /// <param name="packeter"> 打包方法. </param> /// <param name="length"> [out] 接收到数据长度. </param> /// /// <returns> 解包出来的消息条数(注意不是长度). </returns> internal int UnpackReceiveData(IPacket packeter, out int length) { lock (this._lockReserveData) { //拼接所有的已接受数据 byte[] alldata = _reserveQueuePacked.GetDataOnce(_reserveData); _reserveData = null;//清空已经无用的_reserveData if (alldata == null) { length = 0; //长度为0 //这个情形在客户端狂发速度过快的时候容易出现,但是不影响接收,所以去掉这个日志 //DxDebug.LogWarning("Token.UnpackReceiveData(): alldata为null!"); return(0); } length = alldata.Length; //传出这个数据长度 FindPacketResult findPacketResult = packeter.FindPacket(alldata, 0); //解包 _reserveData = findPacketResult.reserveData; //更新reserveData if (findPacketResult.dataArr != null) //将结果加入队列 { //记录下一共找到的有效消息条数 int msgCount = findPacketResult.dataArr.Length; for (int i = 0; i < findPacketResult.dataArr.Length; i++)//结果是一个消息数组 { byte[] data = findPacketResult.dataArr[i]; if (data == null) { //这里是否会频繁发生? DxDebug.LogWarning("Token.UnpackReceiveData(): 结果中的data为null!"); break; } //如果不是心跳包才加入接收消息队列 if (!Config.CompareHeartBeat(findPacketResult.dataArr[i]))//Config中的静态函数判断 { if (!_receiveQueue.EnqueueMaxLimit(findPacketResult.dataArr[i])) { DxDebug.LogWarning("Token.UnpackReceiveData():接收已解包的数据队列 丢弃了一段数据"); } } else { DxDebug.LogFileOnly("Token.UnpackReceiveData():接收到了心跳包 TokenID:" + this.ID); } } LastMsgReceTickTime = DateTime.Now.Ticks; //记录最近一次接收到消息的时间 //DxDebug.Log("某个token接收到了 " + findPacketResult.data.Length + "条消息"); return(msgCount); } else { DxDebug.LogWarning("Token.UnpackReceiveData():接收到数据,经过FindPacket(),但是没有找到有效消息!"); return(0); } } }