예제 #1
0
        /// <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);
                }
            }
        }