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 { } }
/// <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); } }
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); } }
private void ProcessMsg(NetWorkMsg msg) { if (msg != null) { //DxDebug.Log("取到了一条消息,当前队列长度: " + _msgQueue.Count); switch (msg.type) { case NetWorkMsg.Tpye.S_Start: DoStart(msg); break; case NetWorkMsg.Tpye.S_Send: DoSend(msg); break; case NetWorkMsg.Tpye.S_Receive: //DxDebug.Log("DoReceive()"); DoReceive(msg); //DxDebug.Log("DoReceive() 结束"); break; case NetWorkMsg.Tpye.S_SendAll: DoSendAll(msg); break; default: break; } } }
/// <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> /// 线程函数,向所有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="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> /// 向某个token发送一条数据。直接使用Token对象来发送 /// </summary> /// <param name="token"></param> /// <param name="data"></param> public void Send_(Token token, byte[] data) { NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Send, data, token.ID); msg.token = token; AddMessage(msg); }
///------------------------------------------------------------------------------------------------- /// <summary> 向某个token发送一条数据. </summary> /// /// <remarks> Dx, 2017/6/26. </remarks> /// /// <param name="token"> </param> /// <param name="data"> 要发送的数据. </param> ///------------------------------------------------------------------------------------------------- public void Send(Token token, byte[] data) { NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Send, null, token.ID); token.AddSendData(data, 0, data.Length); msg.token = token; AddMessage(msg); }
/// <summary> /// 向某个token发送一条数据。 /// </summary> /// <param name="tokenID">tokenID</param> /// <param name="data">要发送的数据</param> public void Send(int tokenID, byte[] data) { //DxDebug.Log("信号量: 发送"); NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Send, data, tokenID); msg.token = TokenManager.GetInstance().GetToken(tokenID); AddMessage(msg); }
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 OnReceive(Token token) { //DxDebug.Log("信号量: 接收"); NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Receive, null, token.ID); msg.token = token; AddMessage(msg);//debug:这里可以不传ID,直接传Token引用 //DoReceive(msg);//debug:直接使用这个小线程(结果:貌似性能没有明显提高,也貌似没有稳定性的问题) }
/// <summary> /// 连接服务器,输入IP和端口号。会强制重新初始化整个类,这样起到底层重启的作用。 /// </summary> /// <param name="host">主机IP</param> /// <param name="port">端口号</param> public void Connect(string host, int port) { try { DxDebug.LogConsole("DNClient.Connect():连接服务器 主机:" + host + " 端口:" + port); //标记正在连接 IsConnecting = true; //if (_disposed) //{ // DxDebug.LogConsole("DNClient.Connect():这个类对象是被释放状态,重新初始化"); Init(); //} //进行一次连接的时候,把消息队列清空 Clear(); Interlocked.Exchange(ref this._host, host); //给类成员赋值 Interlocked.Exchange(ref this._port, port); //给类成员赋值 NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Connect); } else { msg.Reset(NetWorkMsg.Tpye.C_Connect); } AddMessage(msg); LastMsgReceTickTime = DateTime.Now.Ticks; LastMsgSendTickTime = DateTime.Now.Ticks; } catch (Exception e) { IsConnecting = false;//连接失败了 DxDebug.LogError("DNClient.Connect():异常:" + e.Message); if (EventError != null) { try { EventError(this, EventType.ConnectError, e);//事件类型:ConnectError } catch (Exception e2) { DxDebug.LogWarning("DNClient.Connect():执行EventError事件异常:" + e2.Message); } } Dispose();//释放 } }
private void OnSend(Token token) { if (token.SendQueueCount > 0) //如果待发送队列里有消息这里应该不需要这个判断了token.SendingCount < MAX_TOKEN_SENDING_COUNT && { //DxDebug.Log("OnSend 信号量: 发送"); NetWorkMsg msg = new NetWorkMsg(NetWorkMsg.Tpye.S_Send, null, token.ID); msg.token = token; AddMessage(msg); //DoSend(msg);//debug:直接使用这个小线程(结果:貌似性能没有明显提高,也貌似没有稳定性的问题) } else { } }
/// <summary> /// 异步的关闭socket和线程,会在消息队列中执行完这个消息之前的所有消息后,才会执行。 /// </summary> public void Close() { DxDebug.LogConsole("DNClient.Close():进入了close函数!"); NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_AsynClose); } else { msg.Reset(NetWorkMsg.Tpye.C_AsynClose); } AddMessage(msg); }
/// <summary> /// 加入一条要执行的消息,如果加入的过快而无法发送,则将产生信号量溢出异常,表明当前发送数据频率要大于系统能力 /// </summary> /// <param name="msg"></param> internal void AddMessage(NetWorkMsg msg) { try { if (msg != null) { _msgQueue.Enqueue(msg); } if (_curSemCount < 1) //信号量剩余较少的时候才去释放信号量 { Interlocked.Increment(ref _curSemCount); _msgSemaphore.Release(); } } catch (SemaphoreFullException) { //当前发送数据频率要大于系统能力,可尝试增加消息队列长度 string msgtype = ""; switch (msg.type) { case NetWorkMsg.Tpye.S_Start: msgtype = "S_Start"; break; case NetWorkMsg.Tpye.S_Send: msgtype = "S_Send"; break; case NetWorkMsg.Tpye.S_Receive: msgtype = "S_Receive"; break; default: break; } DxDebug.LogError("DNServer.AddMessage():大于系统能力,当前最后一条:" + msgtype); throw; } catch (Exception e) { DxDebug.LogError("DNServer.AddMessage():*****发生错误! " + e.Message); throw; } }
private void OnReceive() { if (this._isDebugLog) { DxDebug.LogConsole("-----------EventHandler:进入了OnReceive回调!"); } NetWorkMsg msg = _msgPool.Dequeue(); if (msg == null) { msg = new NetWorkMsg(NetWorkMsg.Tpye.C_Receive); } else { msg.Reset(NetWorkMsg.Tpye.C_Receive); } AddMessage(msg); }
private void DoReceive(NetWorkMsg msg) { string debugStr = ""; try { Token token = msg.token; if (token != null) { int length; debugStr = "开始执行token.UnpackReceiveData(_packet, out length);\r\n"; int msgCount = token.UnpackReceiveData(_packet, out length); debugStr = "执行token.UnpackReceiveData(_packet, out length)完毕!\r\n"; if (msgCount > 0) //解包有数据 { debugStr = "开始执行状态统计递增一条记录\r\n"; Interlocked.Add(ref Status.CountReceive, msgCount); //状态统计递增一条记录 if (EventTokenReceData != null) //发出事件:有收到客户端消息 { try { EventTokenReceData(token); } catch (Exception e) { DxDebug.LogWarning("DNServer.DoReceive():执行外部事件EventTokenReceData 异常 " + e.Message); } } } debugStr = "开始执行状态统计递增接收数据长度\r\n"; Interlocked.Add(ref Status.CountReceiveBytes, length);//状态统计递增接收数据长度 } } catch (Exception e) { DxDebug.LogWarning("DNServer.DoReceive():异常 " + e.Message + "debugStr=" + debugStr); } }
/// <summary> /// 线程函数:发送 /// </summary> /// <param name="msg">这个消息参数的arg1为tokenID</param> private void DoSend(NetWorkMsg msg) { try { Token token = msg.token; if (token == null) { return; } if (msg.data != null) //添加该条数据 { token.AddSendData(msg.data, 0, msg.data.Length); } //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.DoSend():异常 " + e.Message); } }
/// <summary> /// 加入一条要执行的消息,如果加入的过快而无法发送,则将产生信号量溢出异常,表明当前发送数据频率要大于系统能力 /// </summary> /// <param name="msg"></param> internal void AddMessage(NetWorkMsg msg) { if (_disposed) { DxDebug.LogWarning("DNClient.AddMessage():DNClient对象已经被释放,不能再加入消息。msgType = " + msg.type.ToString()); return; } try { DxDebug.Log("DNClient.AddMessage():向消息队列中添加消息"); if (msg != null) { _msgQueue.Enqueue(msg); //消息进队列 } if (_curSemCount < 1) //如果当前的信号量剩余不多的时候 { Interlocked.Increment(ref _curSemCount); _msgSemaphore.Release();// 释放信号量 } //发送数据队列长度为128则认为消息已经积攒较长 if (_packet2.SendMsgCount > 128 && _isQueueFull == false)//MAX_SEND_DATA_QUEUE { _isQueueFull = true; if (EventSendQueueIsFull != null) { try { EventSendQueueIsFull(this); } catch (Exception e) { DxDebug.LogWarning("DNClient.AddMessage():执行事件EventMsgQueueIsFull异常:" + e.Message); } } if (_isDebugLog) { DxDebug.LogWarning("DNClient.AddMessage():向消息队列中添加消息,发送队列长度较长:" + _packet2.SendMsgCount); } } else if (_isQueueFull)//如果现在的状态是发送队列较长的状态,那么再去记录峰值长度 { if (_sendQueuePeakLength < _packet2.SendMsgCount) { _sendQueuePeakLength = _packet2.SendMsgCount;//记录当前的峰值长度 } } } catch (SemaphoreFullException) { //当前发送数据频率要大于系统能力,可尝试增加消息队列长度 string msgtype = ""; switch (msg.type) { case NetWorkMsg.Tpye.C_Connect: msgtype = "C_Connect"; break; case NetWorkMsg.Tpye.C_Send: msgtype = "C_Send"; break; case NetWorkMsg.Tpye.C_Receive: msgtype = "C_Receive"; break; default: break; } DxDebug.LogError("DNClient.AddMessage():大于系统能力,当前最后一条:" + msgtype); //throw;//这个throw还是应该去掉 _msgPool.EnqueueMaxLimit(msg); } catch (Exception e) { DxDebug.LogError("DNClient.AddMessage():异常:" + e.Message); //throw;//这个throw还是应该去掉 _msgPool.EnqueueMaxLimit(msg); } }
private void DoWork() { try { DxDebug.LogConsole("DNClient.DoWork():-----------通信线程启动!"); while (true) { Interlocked.Exchange(ref _isThreadWorking, 0);//标记当前线程已经停止工作 _msgSemaphore.WaitOne(); Interlocked.Decrement(ref _curSemCount); //递减信号量计数 Interlocked.Exchange(ref _isThreadWorking, 1); //标记当前线程已经正在执行工作 //_cpuTime.WorkStart(); //时间分析计时 while (true) { NetWorkMsg msg = _msgQueue.Dequeue(); if (msg == null) { break; } float waitTime = (DateTime.Now.Ticks - msg.timeTickCreat) / 10000;//毫秒 if (waitTime > _warringWaitTime) { _warringWaitTime += 500; DxDebug.LogWarning("DNClient.DoWork():NetWorkMsg等待处理时间过长!waitTime:" + waitTime); } else if ((_warringWaitTime - waitTime) > 500) { _warringWaitTime -= 500; } if (msg != null) { switch (msg.type) { case NetWorkMsg.Tpye.C_Connect: DoConnect(); break; case NetWorkMsg.Tpye.C_Send: DoSend(msg); break; case NetWorkMsg.Tpye.C_Receive: DoReceive(); break; case NetWorkMsg.Tpye.C_AsynClose: DoClose(); _workThread = null; //把这个成员置为空 return; //执行完就结束了整个线程函数 default: break; } //用过的消息放回池里 _msgPool.EnqueueMaxLimit(msg); } else { // _cpuTime.Calculate();//空闲的话就计算一下 } //long costTime = _cpuTime.WaitStart(); //时间分析计时 } } } catch (Exception e) { DxDebug.LogError("DNClient.DoWork():异常:通信线程执行异常! " + e.Message); } }
private void DoSend(NetWorkMsg msg) { try { if (IsConnected == false) { DxDebug.LogWarning("DNClient.DoSend:当前还未连接到一个主机! "); return; } //DxDebug.Log("-----------DoSend " + " 当前的SendingCount " + _snedingCount); if (_snedingCount >= MAX_SENDING_DATA) { return; } //如果还有待发送的消息 if (_packet2.SendMsgCount > 0) { if (_socketClient.SendData(_packet2))//如果确实发送成功了 { Interlocked.Increment(ref _snedingCount); } LastMsgSendTickTime = DateTime.Now.Ticks;//记录最后发送消息时间 } //byte[][] datas = _sendDataQueue.GetData(); //if (datas != null) //{ // //DxDebug.Log("-----------开始将" + datas.Length + "条数据打包,加到发送队列的尾部"); // for (int i = 0; i < datas.Length; i++) // { // //if (i >= 2) // //{ // // _msgSemaphore.WaitOne();//重要:这里或许应该消耗信号量 // //} // datas[i] = _packet.CompletePack(datas[i]); //依次从预打包数据完成打包数据 //} //DxDebug.Log("-----------数据打包,开始发送 递增_snedingCount, 当前_snedingCount : " + _snedingCount); //发送队列已经较短了的事件 if (_packet2.SendMsgCount < 128 && _isQueueFull == true)// MAX_SEND_DATA_QUEUE / 4 { _isQueueFull = false; if (_isDebugLog) { DxDebug.LogWarning("DNClient.DoSend():发送队列长度已经恢复正常,峰值长度" + _sendQueuePeakLength); } _sendQueuePeakLength = 0;//重计峰值长度 _msgQueue.TrimExcess(); _msgPool.TrimExcess(); if (EventSendQueueIsAvailable != null) { try { EventSendQueueIsAvailable(this); } catch (Exception e2) { DxDebug.LogWarning("DNClient.DoSend():执行事件EventMsgQueueIsAvailable异常:" + e2.Message); } } } } catch (Exception e) { DxDebug.LogWarning("DNClient.DoSend():异常: " + e.Message); } }