为什么节俭TBinaryProtocol读取recv数据比尺寸+内容更复杂

时间:2015-08-26 01:15:25

标签: c++ thrift

Thrift版本是0.8。我在客户端使用C ++实现我自己的thrift传输层,协议使用Binary,我的服务器使用帧传输和二进制协议,并且没有问题。我得到了#34;没有更多的数据可供阅读" TTransport.h中的异常readAll函数。我跟踪了调用链接,在TBinaryProtocol.tcc中找到

template <class Transport_>
uint32_t TBinaryProtocolT<Transport_>::readMessageBegin(std::string& name,
                                                        TMessageType& messageType,
                                                        int32_t& seqid) {
  uint32_t result = 0;
  int32_t sz;
  result += readI32(sz);      **//sz should be the whole return buf len without the first 4 bytes?**

  if (sz < 0) {
    // Check for correct version number
    int32_t version = sz & VERSION_MASK;
    if (version != VERSION_1) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
    }
    messageType = (TMessageType)(sz & 0x000000ff);
    result += readString(name);
    result += readI32(seqid);
  } else {
    if (this->strict_read_) {
      throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
    } else {
      // Handle pre-versioned input
      int8_t type;
      result += readStringBody(name, sz);
      result += readByte(type);         **//No more data to read in buf, so exception here**
      messageType = (TMessageType)type;
      result += readI32(seqid);
    }
  }
  return result;
}

所以我的问题是:在帧传输中,数据结构只应该是大小+内容(结果,seqid,函数名称....),这正是我的服务器包。然后我的客户端读取前4个字节lenth,并使用它来获取整个内容,还有其他任何东西现在要读吗?

这是我的客户端代码,我相信很简单。我强调的最重要部分。

class CthriftCli
{
......
    TMemoryBuffer write_buf_;
    TMemoryBuffer read_buf_;

    enum CthriftConn::State state_;
    uint32_t frameSize_;
};


void CthriftCli::OnConn4SgAgent(const TcpConnectionPtr& conn)
{
    if(conn->connected() ){
        conn->setTcpNoDelay(true);
        wp_tcp_conn_ = boost::weak_ptr<muduo::net::TcpConnection>(conn);

        if(unlikely(!(sp_countdown_latch_4_conn_.get()))) {
            return 0;
        }

    sp_countdown_latch_4_conn_->countDown();

    }
}

void CthriftCli::OnMsg4SgAgent(const muduo::net::TcpConnectionPtr& conn,
                                 muduo::net::Buffer* buffer,
                                 muduo::Timestamp receiveTime)
{
    bool more = true;
  while (more)
  {
    if (state_ == CthriftConn::kExpectFrameSize)
    {

 if (buffer->readableBytes() >= 4)
      {
        frameSize_ = static_cast<uint32_t>(buffer->peekInt32());
        state_ = CthriftConn::kExpectFrame;
      }
      else
      {
        more = false;
      }
    }
    else if (state_ == CthriftConn::kExpectFrame)
    {
      if (buffer->readableBytes() >= frameSize_)
      {
        uint8_t* buf = reinterpret_cast<uint8_t*>((const_cast<char*>(buffer->peek())));

        read_buf_.resetBuffer(buf, sizeof(int32_t) + frameSize_, TMemoryBuffer::COPY); **// all the return buf, include first size bytes**

        if(unlikely(!(sp_countdown_latch_.get()))){
            return;
        }

        sp_countdown_latch_->countDown();

        buffer->retrieve(sizeof(int32_t) + frameSize_);
        state_ = CthriftConn::kExpectFrameSize;
      }
      else
      {
        more = false;
      }
    }
  }
}

uint32_t CthriftCli::read(uint8_t* buf, uint32_t len) {
    if (read_buf_.available_read() == 0) {

    if(unlikely(!(sp_countdown_latch_.get()))){
        return 0;
    }

    sp_countdown_latch_->wait();
  }

  return read_buf_.read(buf, len);
}

void CthriftCli::readEnd(void) {
  read_buf_.resetBuffer();
}


void CthriftCli::write(const uint8_t* buf, uint32_t len) {
  return write_buf_.write(buf, len);
}

uint32_t CthriftCli::writeEnd(void) 
{
    uint8_t* buf;
  uint32_t size;
  write_buf_.getBuffer(&buf, &size);

if(unlikely(!(sp_countdown_latch_4_conn_.get()))) {
    return 0;
}

sp_countdown_latch_4_conn_->wait();

TcpConnectionPtr sp_tcp_conn(wp_tcp_conn_.lock());

    if (sp_tcp_conn && sp_tcp_conn->connected()) {
      muduo::net::Buffer send_buf;
      send_buf.appendInt32(size);
      send_buf.append(buf, size);
      sp_tcp_conn->send(&send_buf);

      write_buf_.resetBuffer(true);
    } else {
#ifdef MUDUO_LOG
        MUDUO_LOG_ERROR << "conn error, NOT send";
#endif
    }

return size;
}

那么请给我一些关于此的提示?

0 个答案:

没有答案