Thrift的TProtocol类体系原理及源码详解:二进制协议类TBinaryProtocolT

具体参数的写入函数根据参数的类型具体处理并写入到服务器端。这样整个函数 调用就做完了,剩下的就是处理写入后的一些善后处理,看具体代码有注释。

当函数 调用的消息发送出去以后就开始准备接收函数远程调用的结果(异步调用除外),这里接收 Log函数调用返回结果的函数是recv_log,代码如下:

ResultCode 

scribeClient::recv_Log()
    
{
    
  int32_t rseqid = 0;
    
  std::string fname;
    
  ::apache::thrift::protocol::TMessageType mtype;//接收返回消息的类型
    
  iprot_->readMessageBegin(fname, mtype, rseqid);//读取返回结果的消息
    
  if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {//处理返回消息是异常的情况
    
    ::apache::thrift::TApplicationException x;
    
    x.read(iprot_);//读取异常信息
    
    iprot_->readMessageEnd();
    
    iprot_->getTransport()->readEnd();
    
    throw x;//抛出异常信息
    
  }
    
  if (mtype != ::apache::thrift::protocol::T_REPLY) {//处理不是正常回复的结果
    
    iprot_->skip(::apache::thrift::protocol::T_STRUCT);
    
    iprot_->readMessageEnd();
    
    iprot_->getTransport()->readEnd();
    
  }
    
  if (fname.compare("Log") != 0) {//比较是否是Log函数调用返回的结果
    
    iprot_->skip(::apache::thrift::protocol::T_STRUCT);
    
    iprot_->readMessageEnd();
    
    iprot_->getTransport()->readEnd();
    
  }
    
  ResultCode _return;
    
  scribe_Log_presult result;
    
  result.success = &_return;
    
  result.read(iprot_);//读取结果信息
    
  iprot_->readMessageEnd();
    
  iprot_->getTransport()->readEnd();
    
  if (result.__isset.success) {//成功就正常返回,否则抛出异常信息
    
    return _return;
    
  }
    
  throw ::apache::thrift::TApplicationException

(::apache::thrift::TApplicationException::MISSING_RESULT, 
    
"Log failed: unknown result");//抛出不知道结果的异常信息,调用失败了
    
}

接收RPC调用结果的函数都是根据返回消息的类型做相应处理,不成功就抛出相应 的异常信息。首先这里调用二进制协议的readMessageBegin函数读取由二进制写入的消息( 这个当然是服务器端写入的),这个函数代码实现如下:

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);//读取消息的头部(可能是协议版本号和消息类型的组合,也可能直接是消息)
    
  if (sz < 0) {//如果小于0(就是二进制为第一位以1开头,说明是带有协议版本号的
    
    // 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);//取得函数调用ID号
    
  } else {
    
    if (this->strict_read_) {//要求读协议本版号,但是这种情况是不存在协议版本号的所以抛出异常
    
      throw TProtocolException(TProtocolException::BAD_VERSION,
    
 "No version identifier... old protocol client in strict mode?");
    
    } else {
    
      int8_t type;
    
      result += readStringBody(name, sz);//读取消息名称(也就是函数名称)
    
      result += readByte(type);//读取消息类型
    
      messageType = (TMessageType)type;
    
      result += readI32(seqid);//读取函数调用ID号
    
    }
    
  }
    
  return result;//f返回读取数据的长度
    
}

http://www.bianceng.cn/a/2014/0215/39708_3.htm



你可能感兴趣的:(Thrift的TProtocol类体系原理及源码详解:二进制协议类TBinaryProtocolT)