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

  • 相关阅读:
    ubuntu如何设置dns?
    docker服务无法启动如何处理?
    yocto编译时报错"fontconfig-2.12.1/src/fcmatch.c:324:63: error: ‘PRI_CHAR_WIDTH_STRONG' undeclared here (not in a function); did you mean ‘PRI_WIDTH_STRONG’?"
    git如何将当前仓库的远程分支推到一个新的仓库中?
    linux下如何制作ubuntu系统启动盘(sd)?
    yocto编译时报错"glibc/locale/xlocale.h:39:4: note: previous declaration of '__locale_t' was here"
    19、异常处理
    18、文件与目录
    17、python对内存的使用
    16、正则表达式
  • 原文地址:https://www.cnblogs.com/shouhongxiao/p/3702016.html
Copyright © 2011-2022 走看看