public AsyncSendBufferManager(int bufferSize)
 {
     m_dynamicBufferManager = new DynamicBufferManager(bufferSize);
     m_sendBufferList = new List<SendBufferPacket>();
     m_sendBufferPacket.Offset = 0;
     m_sendBufferPacket.Count = 0;
 }
Example #2
0
        ///// <summary>
        ///// 收集監視器數據之命令統計開始
        ///// </summary>
        //private void CommandStatStart()
        //{
        //    //命令當前并發數
        //    ServerStatistics.Concurrent_Commands++;
        //    //命令最高并發數
        //    if (ServerStatistics.MaxConcurrent_Commands < ServerStatistics.Concurrent_Commands)
        //        ServerStatistics.MaxConcurrent_Commands = ServerStatistics.Concurrent_Commands;
        //}

        ///// <summary>
        ///// 收集監視器數據之命令統計結束
        ///// </summary>
        //private void CommandStatEnd(long ElapsedMilliseconds)
        //{
        //    //命令當前并發數
        //    ServerStatistics.Concurrent_Commands--;
        //    //命令當前執行時長(ms)
        //    ServerStatistics.DurationTime_Command = (int)ElapsedMilliseconds;
        //    //命令最大執行時長(ms)
        //    if (ServerStatistics.MaxDurationTime_Command < ServerStatistics.DurationTime_Command)
        //        ServerStatistics.MaxDurationTime_Command = ServerStatistics.DurationTime_Command;
        //}

        /// <summary>
        /// 掃描所有可以發送的完整包
        /// </summary>
        /// <param name="userToken"></param>
        /// <param name="receiveBuffer"></param>
        /// <returns></returns>
        private bool PreparePackages(SocketUserToken userToken, DynamicBufferManager receiveBuffer)
        {
            try
            {
                //error = false;
                //Test
                //System.Diagnostics.Debug.WriteLine("調用:PreparePackages...");
                //System.Text.Encoding.UTF8.GetString(LxTcpServer.Protocol.ParseProtocol.GetByteBuffer(receiveBuffer.Buffer, 0, receiveBuffer.DataCount)).TrimEnd('\0')
                bool CommandResult = false;
                Stopwatch sw = new Stopwatch();
                //判斷緩存中剩餘的數據是否足夠計算完整包
                if (receiveBuffer.DataCount - m_packageOffset < MSGINFOHEAD.BodyLength)
                {
                    if (m_readyPackage > 0)
                    {
                        //已經收集到所有可發送的完整包
                        //m_doProcessCommand = true;
                        //return true;
                        userToken.FirstPacket = true;
                        m_packageOffset = 0;

                        //收集監視器數據之命令統計開始
                        ServerStatistics.CommandStatStart();
                        //開始計時
                        sw.Start();
                        //開始發送
                        CommandResult = ProcessCommand(userToken);
                        //結束計時
                        sw.Stop();
                        //收集監視器數據之命令統計結束
                        ServerStatistics.CommandStatEnd(sw.ElapsedMilliseconds);
                        //重置計時器
                        sw.Reset();

                        return CommandResult;
                    }
                    else
                    {
                        //繼續收
                        return true;
                    }
                }

                int DataLen = 0;
                // #Mark 5#  <-不要刪除這個標記!!
                //1.包體長度(16進制轉10進制)
                byte[] DataLenBuffer = ParseProtocol.GetByteBuffer(receiveBuffer.Buffer, m_packageOffset, MSGINFOHEAD.BodyLength);
                try
                {
                    DataLen = ParseProtocol.Convert16To10(Encoding.UTF8.GetString(DataLenBuffer));
                    if (DataLen == 0)
                    {
                        //如果類別不是S(簽名為空),就說明數據錯誤.
                        if (Encoding.UTF8.GetString(receiveBuffer.Buffer, m_packageOffset + MSGINFOHEAD.BodyLength, 1) != "S")
                        {
                            //視為異常
                            DataLen = -1;
                        }
                    }
                }
                catch
                {
                    //異常
                    DataLen = -1;
                }
                //如果是用戶修改簽名為空白,此處就是0.
                //if (DataLen == 0)
                if (DataLen < 0)
                {
                    //if (userToken.BindingUser != null && userToken.ConnectSocket != null && userToken.ConnectSocket.Connected)
                    //{
                    //    #region " 沒找到出錯原因,暫時特殊處理一下 "

                    //    try
                    //    {
                    //        if (m_packageOffset == 1026 && !userToken.FirstPacket && receiveBuffer.DataCount == 1056)
                    //        {
                    //            //先針對1026 - 1056的錯誤特別處理一下
                    //            //錯誤描述:客戶端:D026533信息異常,包頭:    的長度小於0. PackageOffset:1026.FirstPackage:False.
                    //            //         完整信息(Bytes:1056):00016D026533
                    //            //修正 PackageOffset 和 FirstPackage
                    //            m_packageOffset = 0;
                    //            userToken.FirstPacket = true;
                    //            DataLen = 1;
                    //            string msg = Encoding.UTF8.GetString(receiveBuffer.Buffer, 0, receiveBuffer.DataCount);
                    //            LogHelper.WriteLog("BaseProcessor.PreparePackages", "發生1026-1056錯誤,數據已修正." + "\r\n完整信息(緩存Bytes:" + receiveBuffer.DataCount.ToString() + ",取出數據實際長度:" + msg.Length.ToString() + "):" + msg);
                    //        }
                    //        else if (m_packageOffset == 5121 && !userToken.FirstPacket && receiveBuffer.DataCount == 5131)
                    //        {
                    //            //先針對5121 - 5131的錯誤特別處理一下 ==>> 這個問題已經解了:因為未對簽名為空的情況進行處理,數據總長應該加上尾包長度,再去移除) <<==
                    //            //錯誤描述:客戶端:D037198信息異常,包頭:    的長度小於0. PackageOffset:5121.FirstPackage:False.
                    //            //         完整信息(Bytes:5131):100016D037198
                    //            //將第一位無效數據移除
                    //            receiveBuffer.Clear(1);
                    //            //修正 PackageOffset 和 FirstPackage
                    //            m_packageOffset = 0;
                    //            userToken.FirstPacket = true;
                    //            DataLen = 1;
                    //            string msg = Encoding.UTF8.GetString(receiveBuffer.Buffer, 0, receiveBuffer.DataCount);
                    //            LogHelper.WriteLog("BaseProcessor.PreparePackages", "發生5121-5131錯誤,數據已修正." + "\r\n完整信息(緩存Bytes:" + receiveBuffer.DataCount.ToString() + ",取出數據實際長度:" + msg.Length.ToString() + "):" + msg);
                    //        }
                    //    }
                    //    catch(Exception ex)
                    //    {
                    //        LogHelper.WriteLog("BaseProcessor.PreparePackages", "嘗試修正數據時出錯:" + ex.Message);
                    //        return false;
                    //    }

                    //    #endregion
                    //}
                    //else
                    //{
                    if (userToken.BindingUser != null)
                        LogHelper.WriteLog("BaseProcessor.PreparePackages", "客戶端:" + userToken.BindingUser.ID + "信息異常,包頭:" + Encoding.UTF8.GetString(DataLenBuffer) + "的長度小於0. PackageOffset:" + m_packageOffset.ToString() + ".FirstPackage:" + userToken.FirstPacket.ToString() + ".\r\n完整信息(Bytes:" + receiveBuffer.DataCount.ToString() + "):" + Encoding.UTF8.GetString(receiveBuffer.Buffer, 0, receiveBuffer.DataCount)); //.TrimEnd('\0')
                    else
                        LogHelper.WriteLog("BaseProcessor.PreparePackages", "UserToken.BindingUser為空.信息異常,包頭:" + Encoding.UTF8.GetString(DataLenBuffer) + "的長度小於0.");//.TrimEnd('\0')
                    return false;
                    //}
                }

                //$Mark 1$  <-不要刪除這個標記!!
                //包頭+包體+包尾長度比當前已經收到的長度大.(需要加上包頭和包尾的長度)
                if (ParseProtocol.GetHeadPacketLength(userToken.FirstPacket) + DataLen + MSGINFOEND.EofLength + m_packageOffset > receiveBuffer.DataCount)
                {
                    if (m_readyPackage > 0)
                    {
                        //已經收集到所有可發送的完整包
                        //m_doProcessCommand = true;
                        //return true;
                        userToken.FirstPacket = true;
                        m_packageOffset = 0;

                        //收集監視器數據之命令統計開始
                        ServerStatistics.CommandStatStart();
                        //開始計時
                        sw.Start();
                        //開始發送
                        CommandResult = ProcessCommand(userToken);
                        //結束計時
                        sw.Stop();
                        //收集監視器數據之命令統計結束
                        ServerStatistics.CommandStatEnd(sw.ElapsedMilliseconds);
                        //重置計時器
                        sw.Reset();

                        return CommandResult;
                    }
                    else
                    {
                        //如果有續包就讀取完成再解包
                        //====================================================================================
                        //====== 以下是分析為什麼偶爾出現心跳包解包錯誤,而m_packageOffset永遠是6的問題 =======
                        //心跳標準長1024+1+1,如果此時receiveBuffer.DataCount沒收足夠(假設只收了1024).就會運行到這里.
                        //此時如果把FirstPacket標記為false并再次接收,就會進入 #Mark 1# 處.
                        //按下來m_packageOffset會被賦值為4+1+1,那麼tailData必然不是1,就進入 #Mark 2# 
                        //因為之前一個完整包都沒收到,所以m_readyPackage是0,必然進入 #Mark 3# 
                        //接下來按FirstPacket為false計算數據包標準長并與receiveBuffer.DataCount比效后,必然進入 #Mark 4#
                        //至此,m_packageOffset變成了6,執行 #Mark 5# 時就報錯了.
                        //====================================================================================
                        //userToken.FirstPacket = false;
                        //解決方案:
                        if (ParseProtocol.GetHeadPacketLength(userToken.FirstPacket) + DataLen + MSGINFOEND.EofLength > receiveBuffer.DataCount)
                        {
                            //目前收到的包還不夠一個標準包長,那就視為是首包
                            userToken.FirstPacket = true;
                        }
                        else
                        {
                            //目前收到的包超過了一個標準包長,那就視為是續包
                            userToken.FirstPacket = false;
                        }
                        return true;
                    }
                }
                else
                {
                    // #Mark 1#  <-不要刪除這個標記!!
                    //收取完整,開始分析是否是完全數據(尾包為1)
                    //記錄下一個包的起始位置
                    m_packageOffset += ParseProtocol.GetHeadPacketLength(userToken.FirstPacket) + DataLen + MSGINFOEND.EofLength;
                    string tailData = Encoding.UTF8.GetString(userToken.ReceiveBuffer.Buffer, m_packageOffset - MSGINFOEND.EofLength, MSGINFOEND.EofLength).TrimEnd('\0');
                    if (tailData == "1")
                    {
                        //當前包收取結束
                        //Test
                        //System.Diagnostics.Debug.WriteLine("發出:" + m_packageLength.ToString());
                        //System.Diagnostics.Debug.WriteLine("Buffer Total:" + receiveBuffer.DataCount.ToString());

                        //收好了(至少有一個完整的包可以發送),開始解包并處理命令
                        userToken.FirstPacket = true;
                        //累計待發送的包個數(由ProcessCommand清除)
                        m_readyPackage++;
                        //後面達不到最小包長度就放棄掃描
                        DataLen = 1;
                        if (ParseProtocol.GetHeadPacketLength(userToken.FirstPacket) + DataLen + MSGINFOEND.EofLength + m_packageOffset > receiveBuffer.DataCount)
                        {
                            //m_doProcessCommand = true;
                            m_packageOffset = 0;

                            //收集監視器數據之命令統計開始
                            ServerStatistics.CommandStatStart();
                            //開始計時
                            sw.Start();
                            //開始發送
                            CommandResult = ProcessCommand(userToken);
                            //結束計時
                            sw.Stop();
                            //收集監視器數據之命令統計結束
                            ServerStatistics.CommandStatEnd(sw.ElapsedMilliseconds);
                            //重置計時器
                            sw.Reset();

                            return CommandResult;
                        }
                        else
                        {
                            //Test
                            //LogHelper.WriteLog("BaseProcessor.PreparePackages", "尾包值為1(位置:" + (m_packageOffset - 1).ToString() + "),FirstPacket:" + userToken.FirstPacket.ToString() + ",下次將從" + m_packageOffset.ToString() + "開始檢查首包長度.\r\n完整信息(Bytes:" + receiveBuffer.DataCount.ToString() + "):" + Encoding.UTF8.GetString(receiveBuffer.Buffer, 0, receiveBuffer.DataCount).TrimEnd('\0'));

                            //再掃描一次(不用再去接收)
                            return PreparePackages(userToken, receiveBuffer);
                        }
                    }
                    else
                    {
                        // #Mark 2#  <-不要刪除這個標記!!
                        //接下來的一個包一定是續包
                        userToken.FirstPacket = false;

                        if (m_readyPackage > 0)
                        {
                            //雖然是續包,已經收集到所有可發送的完整包,剩下來的數據0位置就是首包
                            userToken.FirstPacket = true;//<-- 2016/04/20 19:51 被1029問題坑得發瘋的時候加的,之前這句沒加...
                            //=============================== 以下是1029錯誤的故事 ===============================
                            //如果這里不賦為true,那麼m_packageOffset被置0后執行ProcessCommand,完成后執行到 #Mark 1#,
                            //然后m_packageOffset會被設置為1029(4+1024+1), 隨後來到 #Mark 2#, 最後 #Mark 3#. 無論此處走哪邊,
                            //都會重新進入PreparePackages,並且此時m_packageOffset為1029,userToken.FirstPacket為false.
                            //但Buffer剩下的卻是一個以首包開始完整數據,結果崩壞!
                            //====================================================================================
                            m_packageOffset = 0;

                            //收集監視器數據之命令統計開始
                            ServerStatistics.CommandStatStart();
                            //開始計時
                            sw.Start();
                            //開始發送
                            CommandResult = ProcessCommand(userToken);
                            //結束計時
                            sw.Stop();
                            //收集監視器數據之命令統計結束
                            ServerStatistics.CommandStatEnd(sw.ElapsedMilliseconds);
                            //重置計時器
                            sw.Reset();

                            return CommandResult;
                        }
                        else
                        {
                            // #Mark 3#  <-不要刪除這個標記!!
                            //如果剩餘已接收數據還可以檢查一次就直接比較
                            DataLen = 1;
                            if (ParseProtocol.GetHeadPacketLength(userToken.FirstPacket) + DataLen + MSGINFOEND.EofLength + m_packageOffset <= receiveBuffer.DataCount)
                            {
                                // #Mark 4#  <-不要刪除這個標記!!
                                return PreparePackages(userToken, receiveBuffer);
                            }
                            else
                            {
                                //繼續接收數據(有效位置就從m_packageOffset開始)
                                return true;
                            }
                        }
                    }
                }
            }
            catch
            {
                //error = true;
                //主動關閉連接
                //userToken.Closing = true;
                return false;
            }
        }
Example #3
0
        public SocketUserToken(int receiveBufferSize)
        {
            m_connectSocket = null;
            m_asyncSendAgent = null;
            m_receiveEventArgs = new SocketAsyncEventArgs();
            m_receiveEventArgs.UserToken = this;
            m_asyncReceiveBuffer = new byte[receiveBufferSize];
            m_receiveEventArgs.SetBuffer(m_asyncReceiveBuffer, 0, m_asyncReceiveBuffer.Length);

            m_sendEventArgs = new SocketAsyncEventArgs();
            m_sendEventArgs.UserToken = this;

            m_receiveBuffer = new DynamicBufferManager(ServerConst.InitBufferSize);
            m_sendBuffer = new AsyncSendBufferManager(ServerConst.InitBufferSize);
            //存放接收到的待處理的數據
            //m_receiveQueue = Queue.Synchronized(new Queue());
            //0表示沒有續包
            //m_restPacketLength = 0;
            //默認為首包
            m_firstPacket = true;
            m_user = new Core.User();

            m_closing = false;
        }