Socket通信中的 BeginReceive與EndReceive


BeginReceive 與endReceive 必須成對出現,如果BeginReceive沒有及時調用endReceive,可能會出現數據被從buffer中讀取二次,如果在下面這行代碼下面加入別的代碼

 就會出現被處理二次的結果 如下

 

public void BeginReceive(SessionListner listner)
        {
            if (listner.State != TSessionState.Active)
            {
                return;
            }
            try
            {
                int bufferOffset = this.BufferManager.GetReceivevBufferOffset(m_bufferBlockIndex);
                WorkSocket.BeginReceive(this.BufferManager.ReceiveBuffer, bufferOffset, this.BufferManager.ReceiveBufferSize, SocketFlags.None, this.EndReceiveDatagram, listner);
                listner.Receive();
            }

            catch (Exception err)  // 讀 Socket 異常,准備關閉該會話
            {
                listner.DisconnectType = TDisconnectType.Exception;
                listner.State = TSessionState.Inactive;//這個客戶狀態不活動了
                //說明發送端口被異常關閉了
                this.OnSessionReceiveException(listner, err);
            }
        }

 上面的  listner.Receive();處理緩存數據方法

 然后再執行

 private void EndReceiveDatagram(IAsyncResult iar)
        {
            SessionListner listner = (iar.AsyncState as SessionListner);

            if (listner.State != TSessionState.Active)
            {
                return;
            }
            try
            {
                int cr = WorkSocket.EndReceive(iar);
                Console.WriteLine(cr);
                if (cr == 0)
                {
                    listner.DisconnectType = TDisconnectType.Normal;
                    listner.State = TSessionState.Inactive;
                    //被關閉了,需要及時關閉
                }
                else
                {
                    listner.LastSessionTime = DateTime.Now;
                    this.BufferManager.RealReceiveSize = cr;
                     this.BeginReceive(listner);
                }
            }

 就出現被二次處理的問題,分析得出:1,在第一次讀取完就處理緩沖數據,2同時進入了EndReceiveDatagram方法,再一次時進入BeginReceive方法 ,但沒有處理完第一次緩存數據,就可能導致處理數據不正確。

需要改成:EndReceiveDatagram中處理數據

 else
                {
                    listner.LastSessionTime = DateTime.Now;
                    this.BufferManager.RealReceiveSize = cr;
                    listner.Receive();
                   
                    this.BeginReceive(listner);
                }

總結:處理數據永遠需要放到接收后處理,BeginReceive在永遠不斷的起線程,而endReceive在不斷的幫它完成回收和結束工作。在Begin中下面放執行代碼有可能有一定問題。也就是在沒有end的時候,沒有阻塞后,再操作共享變量有一定問題,所以begin與end同時操作共享對象或變量時時一定要end之后。無論socket還是一般的異步委托方法。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM