/// <summary>
        /// [Safe]
        /// </summary>
        /// <returns></returns>
        public DuplexSocketEvent Pop()
        {
            DuplexSocketEvent e = default(DuplexSocketEvent);

            lock (_lock)
            {
                if (_freesocketpool.Count > 0)
                {
                    e = _freesocketpool.Dequeue();
                    e.Initialize();
                }
            }

            return(e);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="numConnectMax">最大连接数</param>
        /// <param name="threads">记录系统内开启的线程</param>
        /// <param name="portListen">监听端口</param>
        /// <param name="whiteIps">白名单,哈希表存储的是IP,为null时,关闭白名单过滤</param>
        /// <param name="afterReceiveCallBack">接收到完整的http报文后,系统会调用此函数,在函数内可进行Http Request Body的读取</param>
        /// <param name="beforeSendCallBack">发送报文之前的回调函数,在函数内可进行数据发送前的封装</param>
        public void Start(int numConnectMax, List <Thread> threads,
                          int portListen,
                          HashSet <string> whiteIps,
                          Func <CommuParam, ReceiveBuffParam, bool> afterReceiveCallBack,
                          Func <byte[], byte[]> beforeSendCallBack)
        {
            this._MaxConnectNum = numConnectMax;
            this._whiteIps      = whiteIps;
            CommuEngine._s_DuplexSocketEvents = new DuplexSocketEvent[this._MaxConnectNum];
            CommuEngine._s_EventsPerSocket    = new int[this._MaxConnectNum];
            this._ConnNumPerEngine            = this._MaxConnectNum / this._EngineNum;
            if ((this._MaxConnectNum % this._EngineNum) > 0)
            {
                this._ConnNumPerEngine++;
            }

            #region Init DuplexSocket's DataStructrue

            this._DuplexSocketEventPool = new DuplexSocketEventPool(this._MaxConnectNum);
            for (int i = 1; i < this._MaxConnectNum; i++)
            {
                DuplexSocketEvent duplexSocket = new DuplexSocketEvent(CommuEngine.SIZE_SEND_BUFF, CommuEngine.SIZE_RECV_BUFF, i, portListen);
                duplexSocket.AfterReceiveCallBack = afterReceiveCallBack;
                duplexSocket.BeforeSendCallBack   = beforeSendCallBack;
                this._DuplexSocketEventPool.Push(duplexSocket);
                CommuEngine._s_DuplexSocketEvents[i] = duplexSocket;
            }

            #endregion

            CommuEngine._s_CommuEngineEvents = new AsyncQueue <UInt64> [this._EngineNum];
            this._timerHeaps = new MinHeap <OnTimer> [this._EngineNum];
            for (int i = 0; i < this._EngineNum; i++)
            {
                //OnTimer
                this._timerHeaps[i] = new MinHeap <OnTimer>(this._ConnNumPerEngine);
                CommuEngine._s_CommuEngineEvents[i] = new AsyncQueue <UInt64>();
                WLLibrary.ThreadHandle.StartBackgroundParamerterizedThread(CommuEngine.Instance.MainLoop, i, threads);
            }

            WLLibrary.Communication.Http.TCPListener.Start(portListen, threads);
        }
        /// <summary>
        /// [Safe]
        /// </summary>
        /// <param name="e"></param>
        public void Push(DuplexSocketEvent e)
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }
            else
            {
                if (e.eReceive.AcceptSocket != null)
                {
                    e.eReceive.AcceptSocket = null;
                }

                if (e.eSend.AcceptSocket != null)
                {
                    e.eSend.AcceptSocket = null;
                }

                lock (_lock)
                {
                    _freesocketpool.Enqueue(e);
                }
            }
        }
Ejemplo n.º 4
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 > CommuEngine.s_MaxConnNum - 1)
            {
                idxEnd = CommuEngine.s_MaxConnNum - 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;
                        }

#if PROFILE
                        LogEngine.Write(LOGTYPE.INFO, "Client Have Event:", i.ToString(), ",EventCode:", events.ToString("X"));
#endif

                        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)
                            {
                                //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 Break

                            if (sockDup.IsBreak)
                            {
#if PROFILE
                                LogEngine.Write(LOGTYPE.ERROR, "Recycle Repeat:", socketId.ToString());
#endif
                                continue;
                            }

                            try
                            {
                                socket = sockDup.eReceive.AcceptSocket;
                                if (socket != null)
                                {
                                    //socket.Shutdown(SocketShutdown.Both);
                                    socket.Close();
                                }
                            }
                            catch (Exception ex)
                            {
                                LogEngine.Write(LOGTYPE.ERROR, "MGR_BREAK:", ex.ToString());
                            }
                            finally
                            {
                                sockDup.eReceive.AcceptSocket = sockDup.eSend.AcceptSocket = null;
                                sockDup.SetBreak();
                                this._DuplexSocketEventPool.Push(sockDup);//second

#if PROFILE
                                LogEngine.Write(LOGTYPE.INFO, "Recycle:", socketId.ToString(), "/sid");
#endif
                            }
                            #endregion
                        }
                        else
                        {
                            if (sockDup.IsBreak)
                            {
#if PROFILE
                                LogEngine.Write(LOGTYPE.ERROR, "Send After Recycle:", socketId.ToString());
#endif
                                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);
                }
            }
        }