zoukankan      html  css  js  c++  java
  • 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还是一般的异步委托方法。

  • 相关阅读:
    DBA手记(学习)-library cache pin
    DBA手记(学习)-RAC环境下GES TX报警情况处理
    DBA手记(学习)
    flashback query闪回数据
    在CentOS7上安装MySQL5.7-源码包方式
    PL/SQL注册码
    TortoiseGit的安装与配置
    Git安装配置及第一次上传项目到GitHub
    【IDEA使用技巧】(5) —— IntelliJ IDEA集成Tomcat部署Maven Web项目
    【IDEA使用技巧】(4) —— IDEA 构建Java Maven项目、导入Eclipse项目、多Module Maven项目
  • 原文地址:https://www.cnblogs.com/shouhongxiao/p/3702016.html
Copyright © 2011-2022 走看看