贝贝花花包包店,精品555皮具,钱夹,皮夹

字体:  

关于接收失败或者接收的消息长度为0的问题,急!

gujiwubian 发表于: 2008-8-07 19:18 来源: ACE 开发者

void
CAceClientHandler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
{
{
  ACE_GUARD (ACE_SYNCH_MUTEX, monitor, this->lock_);
  CAceCCharacter * pCharacter = m_pCharacter;
  int nSuccess(0), nBytes_transferred(0);
  {
   ACE_Message_Block & mb = result.message_block ();
   nSuccess = result.success();
   nBytes_transferred = result.bytes_transferred();
   if ( nSuccess && (nBytes_transferred != 0) )
   {
    if ( !m_pRecvHeader )
    {
     m_pRecvHeader = new char[PACK_DATA_SIZE * 2];
    }
    int nThisLen = mb.length();
    if ( pCharacter && pCharacter->IsAddHeader() )
    {
     // 这里假设每次收到一个包,不会收到半包。(不知道服务器发多少字节,没有办法呀!)
     WORD wThisMsgSize   = sizeof(SMG_PK_HEADER) + (WORD)nThisLen;
     wThisMsgSize = MIN(wThisMsgSize, MAX_SMG_PK_SIZE);
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_wtype1  = SMG_PK_TYPE_GENERAL;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_wtype2  = wThisMsgSize;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_nPackSize = wThisMsgSize;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_nID   = -1;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_nConnectionID = -1;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_nGlobalID = -1;
     ((SMG_PK_HEADER *)m_pRecvHeader)->m_aPara[0] = SMG_STOC_OTHER_NO_HEADER_RETURN;
     memcpy( SMG_PK_DATA(m_pRecvHeader), mb.rd_ptr(), nThisLen );
     m_nRecvHeaderLen = MAX_SMG_PK_SIZE; // 唉,开始胡乱搞了。
    }
    else
    {
     if ( m_nRecvHeaderLen + nThisLen > MAX_SMG_PK_SIZE * 2 )
     {
      OutputError( SMG_E_NULL, __FILE__, __LINE__, "怎么这么长!<%d>", m_nRecvHeaderLen + nThisLen );
      nSuccess = 0; // 断开吧。
     }
     else
     {
      memcpy( m_pRecvHeader + m_nRecvHeaderLen, mb.rd_ptr(), nThisLen );
      m_nRecvHeaderLen += nThisLen;
     }
    }
   }
   else
   {
    m_nRecvHeaderLen = 0;
   }
   mb.release ();
  }

  if ( nSuccess && nBytes_transferred != 0 )
  {
   if ( pCharacter )
   {
    if ( m_nRecvHeaderLen >= MAX_SMG_PK_SIZE )
    {
     pCharacter->AddRecvPack( m_pRecvHeader );
     // 往前移动一个包
     memcpy( m_pRecvHeader, m_pRecvHeader + MAX_SMG_PK_SIZE, m_nRecvHeaderLen - MAX_SMG_PK_SIZE );
     m_nRecvHeaderLen -= MAX_SMG_PK_SIZE;
    }
    this->initiate_read_stream ();
    return;
   }
   else
   {
    SMG_ASSERT(FALSE);
    OutputError( SMG_E_NULL, __FILE__, __LINE__, "pCharacter 为空!" );
   }
  }
  else
  {
   //TRACE("出错了,要关闭。\r\n");
  }
  }
  //delete this;
  SetInvalid();//这里就断开了!!!!是合理的么?如果不断开,有什么办法补救???另外为什么这里断开的很频繁??是跟网络状况有关么???
}

代码是别人写的,我自己对ACE也只是一知半解,勉强能看懂而已,希望各位大哥帮个忙,给些提示吧!很急的!

最新回复

gujiwubian at 2008-8-07 22:47:32
SetInvalid();这个就是设置客户端断开的函数
wishel at 2008-8-07 23:06:50
接收失败或者接收到0个字节,通常是对方断开了连接,不知道SetInvalid();是做什么的,猜测可能是重传或者清理等其他工作吧。
gujiwubian at 2008-8-08 10:53:15
SetInvalid();跟重传没关系的,就是清理客户端的一些资源。
wishel at 2008-8-08 12:01:29
可能楼主没有弄清楚,那句代码只是当客户端断开时做相应处理操作。并没有说这一定是频繁发生的,客户端主动断开连接,服务端只能做清理释放资源了。
gujiwubian at 2008-8-08 12:07:43
现在的问题是当接收失败或者接收到的数据为0时,客户端就主动断开了。这样的逻辑是合理的么??如果我不想让他断开的话,有什么办法补救么??而且现在的问题是在这里确实是频繁的断开了。
wishel at 2008-8-08 12:37:45
不是当接收失败或者接收到的数据为0时,客户端就主动断开了,而是客户端先断开,服务端才会接收失败或者接收到的数据为0。
至于客户端为什么要断开,服务端没办法知道。能有什么办法补救呢,总不能人家要断开服务端拒绝吧,呵呵。要从客户端找原因。
gujiwubian at 2008-8-11 10:23:59
上面是客户端的代码。你的意思是,造成客户端的接受失败或者接受数据为0时的原因是服务器主动断开,导致客户端接收失败或者接受数据为0的??
gujiwubian at 2008-8-11 10:24:34
不好意思,这两天跑了下图书馆。。。。没来的及回帖。抱歉
gujiwubian at 2008-8-11 10:59:24
另外如果是有一方先断开的话,那么就不会发送数据了吧,另外一端就不存在接收数据的说法了。应该是一直处在监听状态,而不会收到任何数据,那也不会有接收失败或者接收的数据为0的状态出现了
wishel at 2008-8-11 11:35:43
不好意思,之前看错了,以为是服务端的代码
异步读写,一方如果不反应,就会等待,而不会产生complete event并调用handle_*。如果对方断开,肯定是返回,且result状态为失败(也可能受到数据为0)。
现在的代码发生了complete event,那么如果失败或者为0,肯定是对方断开了。如果是对方还没有反应,异步读是一直等下去的,直到成功或者异常,发生complete。
gujiwubian at 2008-8-11 14:12:15
急啊!!!!!!!!
gujiwubian at 2008-8-11 14:13:50
呵呵,我还纳闷呢。。。。恩,听你说的我好像有点明白了,我再看看吧,有什么不会的,再来问你了,谢谢
gujiwubian at 2008-8-11 17:59:53
接收成功,但是接收到的数据大小为0!不知道为什么!!!!疯了
gujiwubian at 2008-8-11 18:15:20
我想问一下,如果是服务器先断开了,那么客户端的接收是否成功和接收到的数据大小这两个数据会是什么样的??
wishel at 2008-8-11 19:55:00
对方主动断开应该是返回失败吧
什么情况下会返回成功但收到数据大小为0我也没搞清楚,应该要看源码了
gujiwubian at 2008-8-11 23:00:03
恩,谢谢你了,可惜问题还是没解决。。。。痛苦啊!
wishel at 2008-8-13 22:30:28
看了下源程序,ACE的异步I/O封装的是OS的异步I/O API,所以result.bytes_transferred ()就是OS的返回结果,比如windows下的ReadFile(),unix下的aio_read()。具体什么情况下返回0就要看OS关于该API的的文档了。

[ 本帖最后由 wishel 于 2008-8-13 22:31 编辑 ]