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

 

 

 

转载于:https://www.cnblogs.com/shouhongxiao/p/3702016.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值