/// <summary> /// 接纳新连接,启动接收,发送,断开处理线程主体 /// </summary> public void MainLoop(object state) { int idxEngine = Convert.ToInt32(state); int numCurLoop = 0, numMaxLoop = 0; Socket socket = null; byte[] sockSendBuf = null; DuplexSocketEvent sockDup = null; UInt64 eventsOuterData = 0uL; int socketId = 0; int events = 0; byte[] sendEachBuffer = null; AsyncQueue <UInt64> eventsOuter = CommuEngine._s_CommuEngineEvents[idxEngine]; UInt64[] dataPoolOnce = new UInt64[CommuEngine.POOL_MAX_LOOP]; MinHeap <OnTimer> timerHeap = this._timerHeaps[idxEngine]; int idxBegin = idxEngine * this._ConnNumPerEngine; if (idxBegin == 0) { idxBegin = 1; } int idxEnd = (idxEngine + 1) * this._ConnNumPerEngine - 1; if (idxEnd > this._MaxConnectNum - 1) { idxEnd = this._MaxConnectNum - 1; } while (this._systemRun) { socket = null; try { numCurLoop = 0; numMaxLoop = eventsOuter.DequeueToArray(dataPoolOnce); while (numCurLoop < numMaxLoop) { eventsOuterData = dataPoolOnce[numCurLoop++]; socketId = (int)(eventsOuterData & 0x00000000FFFFFFFFL); CommuEngine._s_EventsPerSocket[socketId] |= (int)(eventsOuterData >> 32); } for (int i = idxBegin; i <= idxEnd; i++) { events = CommuEngine._s_EventsPerSocket[i]; if (events < 1) { continue; } socketId = i; CommuEngine._s_EventsPerSocket[i] = 0; sockDup = CommuEngine._s_DuplexSocketEvents[socketId]; if ((events & (int)EventType.Event_New) > 0) { #region New Connect socket = sockDup.eReceive.AcceptSocket; try { if (socket != null && !socket.ReceiveAsync(sockDup.eReceive)) { sockDup.ProcessReceive(sockDup.eReceive); } } catch (System.InvalidOperationException) { LogEngine.Write(LOGTYPE.ERROR, sockDup.SocketID.ToString(), "/s,", idxEngine.ToString(), "/idx,", sockDup.eReceive.LastOperation.ToString()); } catch (Exception ex2) { LogEngine.Write(LOGTYPE.ERROR, sockDup.SocketID.ToString(), "/s,", idxEngine.ToString(), "/idx,", ex2.Message); } OnTimer timer = new OnTimer(OnTimer.TimerHeapType.ONCE, 10 * 1000, sockDup.ConnectOnTimer); timerHeap.Push(timer); #endregion } else if ((events & (int)EventType.Event_StopCommu) > 0) { #region Stop if (sockDup.IsBreak) { continue; } try { socket = sockDup.eReceive.AcceptSocket; if (socket != null) { //socket.Shutdown(SocketShutdown.Both); socket.Close(); } } catch (Exception ex) { LogEngine.Write(LOGTYPE.ERROR, "Event_StopCommu:", ex.ToString()); } finally { sockDup.eReceive.AcceptSocket = sockDup.eSend.AcceptSocket = null; sockDup.SetBreak(); if (sockDup.BreakCallBack != null) { sockDup.BreakCallBack(sockDup.commuParam); } } #endregion } else if ((events & (int)EventType.Event_Close) > 0) { #region Close //回收 this._DuplexSocketEventPool.Push(sockDup);//second if (!sockDup.IsBreak) { LogEngine.Write(LOGTYPE.ERROR, "Get Event_StopCommu,But Target Not Break:", sockDup.SocketID.ToString(), "/sid"); } #endregion } else { sockDup = CommuEngine._s_DuplexSocketEvents[socketId]; if (sockDup.IsBreak) { continue; } //if ((events & Event_Receive) > 0) //{ // #region Receive // #endregion //} if ((events & (int)EventType.Event_SendComplet) > 0) { #region SendComplet if (sockDup.SendPool.Count > 0) { events |= (int)EventType.Event_Send; } #endregion } if ((events & (int)EventType.Event_Send) > 0) { #region 处理发放 sockSendBuf = sockDup.SendBuffer; while (sockDup.SendPool.Count > 0) { sendEachBuffer = sockDup.SendPool.First(); #region Concat bytes if (sendEachBuffer.Length <= sockSendBuf.Length) { if (sendEachBuffer.Length <= (sockSendBuf.Length - sockDup.waitSendLen)) { sendEachBuffer = sockDup.SendPool.Dequeue(); Buffer.BlockCopy(sendEachBuffer, 0, sockSendBuf, sockDup.waitSendLen, sendEachBuffer.Length); sockDup.waitSendLen += sendEachBuffer.Length; if (sockDup.waitSendLen >= CommuEngine.MTU_SEND) { break; } } else { break; } } else { sockDup.SendPool.Dequeue();//drop data //LogEngine.Write(LOGTYPE.ERROR, "ProtocolData TooLong Max:", sockSendBuf.Length.ToString(), ",", sockDup.Profile); } #endregion } #region ProcessSend if (sockDup.waitSendLen > 0) { sockDup.eSend.SetBuffer(sockSendBuf, 0, sockDup.waitSendLen); sockDup.sendBeginTicks = DateTime.Now.Ticks; socket = sockDup.eSend.AcceptSocket; try { if (socket != null && socket.Connected && !socket.SendAsync(sockDup.eSend)) { sockDup.ProcessSend(sockDup.eSend); } } catch (SocketException) { if (sockDup.eSend.SocketError == SocketError.MessageSize) { sockDup.Break(CommuBreak.SERVER_SEND_DATA_SIZE); } else { sockDup.Break(CommuBreak.SERVER_SEND_EXPECT); } } } #endregion #endregion } } } //OnTimer while (timerHeap.Count > 0 && timerHeap.Root.Weight <= DateTime.Now.Ticks) { if (timerHeap.Root.TimeOutCallBack != null) { timerHeap.Root.TimeOutCallBack(null); } if (timerHeap.Root.Type == OnTimer.TimerHeapType.ALWAYS) { timerHeap.ChangeWeight(timerHeap.Root.HeapIndex, timerHeap.Root.RefreshWeight()); } else { timerHeap.PopRoot(); } } } catch (System.Exception ex) { LogEngine.Write(LOGTYPE.ERROR, "CommuEngine MainLoop:", ex.ToString()); } finally { Thread.Sleep(1); } } }