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还是一般的异步委托方法。

 

 

 

posted @ 2014-04-30 19:09  一点点水  阅读(12913)  评论(1编辑  收藏  举报