示例#1
0
        public void Start(int numConnectMax, List <Thread> threads,
                          int portListen,
                          Func <CommuParam, ReceiveBuffParam, int> afterReceiveCallBack,
                          Func <object, CommuParam, byte[]> beforeSendCallBack,
                          Action <CommuParam> breakCallBack)
        {
            this._MaxConnectNum = numConnectMax;
            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, CommuEngine.SIZE_RECV_BUFF, i, portListen);
                duplexSocket.AfterReceiveCallBack = afterReceiveCallBack;
                duplexSocket.BeforeSendCallBack   = beforeSendCallBack;
                duplexSocket.BreakCallBack        = breakCallBack;
                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.Tcp.TCPListener.Start(portListen, threads);
        }
示例#2
0
        /// <summary>
        /// 处理连接
        /// </summary>
        /// <param name="e"></param>
        private void ProcessAccept(SocketAsyncEventArgs e)
        {
            try
            {
                if (e.AcceptSocket != null && e.AcceptSocket.Connected)
                {
                    try
                    {
                        DuplexSocketEvent duplexSocket = CommuEngine.Instance.GetFreeDuplexSocket();
                        if (duplexSocket != null)
                        {
                            IPEndPoint ipepAcceptAddress = (IPEndPoint)e.AcceptSocket.RemoteEndPoint;
                            duplexSocket.eReceive.AcceptSocket = duplexSocket.eSend.AcceptSocket = e.AcceptSocket;

                            duplexSocket.commuParam.ip   = ipepAcceptAddress.Address.ToString();
                            duplexSocket.commuParam.port = ipepAcceptAddress.Port;

                            CommuEngine.Instance.AddEvent(duplexSocket.SocketID, EventType.Event_New);
                        }
                        else
                        {
                            //e.AcceptSocket.Shutdown(SocketShutdown.Both);
                            e.AcceptSocket.Close();
                        }

                        e.AcceptSocket = null;
                    }
                    catch (Exception)
                    {
                        //LogEngine.Write(LOGTYPE.ERROR, ex.ToString());
                    }
                }
            }
            catch (Exception)
            {
                //LogEngine.Write(LOGTYPE.ERROR, "【严重】监听处理异常,原因:" + ex.ToString());
            }
            finally
            {
                this.StartAccept(ref e);
            }
        }
示例#3
0
        /// <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);
                }
            }
        }
示例#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 > 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);
                }
            }
        }