首页 > 其他分享 >Thrift 消息序列化分析过程

Thrift 消息序列化分析过程

时间:2023-05-22 18:32:33浏览次数:31  
标签:return double dub writeDouble cast 消息 ENDIAN 序列化 Thrift

序列化浮点型数据流程

	bitwise_cast<unsigned __int64,double>(double from) 行 74	C++
	apache::thrift::protocol::TBinaryProtocolT<apache::thrift::transport::TTransport>::writeDouble(const double dub) 行 171	C++
 	apache::thrift::protocol::TVirtualProtocol<apache::thrift::protocol::TBinaryProtocolT<apache::thrift::transport::TTransport>,apache::thrift::protocol::TProtocolDefaults>::writeDouble_virt(const double dub) 行 414	C++
	apache::thrift::protocol::TProtocol::writeDouble(const double dub) 行 458	C++
 	ucrtbased.dll!60dfa298()	未知
 	[下面的框架可能不正确和/或缺失,没有为 ucrtbased.dll 加载符号]	未知
 	ucrtbased.dll!60df9fd9()	未知
 	kernel32.dll!74a86359()	未知
 	ntdll.dll!76ee8944()	未知
 	ntdll.dll!76ee8914()	未知
template <class Transport_>
uint32_t TBinaryProtocolT<Transport_>::writeDouble(const double dub) {
  BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t));
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);

  uint64_t bits = bitwise_cast<uint64_t>(dub);
  bits = htonll(bits);
  this->trans_->write((uint8_t*)&bits, 8);
  return 8;
}
xfer += oprot->writeFieldBegin("fFhorizontalValue", ::apache::thrift::protocol::T_DOUBLE, 12);
  xfer += oprot->writeDouble(this->fFhorizontalValue);
  xfer += oprot->writeFieldEnd();
uint32_t writeDouble(const double dub) {
    T_VIRTUAL_CALL();
    return writeDouble_virt(dub);
  }
virtual uint32_t writeDouble_virt(const double dub) {
    return static_cast<Protocol_*>(this)->writeDouble(dub);
  }


double类型保存成整型

通过联合体将double类型转换成整型

// Use this to get around strict aliasing rules.
// For example, uint64_t i = bitwise_cast<uint64_t>(returns_double());
// The most obvious implementation is to just cast a pointer,
// but that doesn't work.
// For a pretty in-depth explanation of the problem, see
// http://www.cellperformance.com/mike_acton/2006/06/ (...)
// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
  BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));

  // BAD!!!  These are all broken with -O2.
  //return *reinterpret_cast<To*>(&from);  // BAD!!!
  //return *static_cast<To*>(static_cast<void*>(&from));  // BAD!!!
  //return *(To*)(void*)&from;  // BAD!!!

  // Super clean and paritally blessed by section 3.9 of the standard.
  //unsigned char c[sizeof(from)];
  //memcpy(c, &from, sizeof(from));
  //To to;
  //memcpy(&to, c, sizeof(c));
  //return to;

  // Slightly more questionable.
  // Same code emitted by GCC.
  //To to;
  //memcpy(&to, &from, sizeof(from));
  //return to;

  // Technically undefined, but almost universally supported,
  // and the most efficient implementation.
  union {
    From f;
    To t;
  } u;
  u.f = from;
  return u.t;
}

大小端数据传输

htonll函数将会对主机字节序转换成网络字节序,然后发送

当前主机的字节序,主要通过包含

 include <boost/detail/endian.hpp>

确定的

小端系统代码

#ifndef __THRIFT_BYTE_ORDER
# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#  define __THRIFT_BYTE_ORDER BYTE_ORDER
#  define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
#  define __THRIFT_BIG_ENDIAN BIG_ENDIAN
# else
#  include <boost/config.hpp>
#  include <boost/detail/endian.hpp>

大端系统代码

#ifndef __THRIFT_BYTE_ORDER
# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#  define __THRIFT_BYTE_ORDER BYTE_ORDER
#  define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN
#  define __THRIFT_BIG_ENDIAN BIG_ENDIAN
# else
#  include <boost/config.hpp>
//#  include <boost/detail/endian.hpp>

问题总结

目前项目上发现传输给客户端的浮点型数据全部变成类似3.40788366E-312等异常数据,其他版本代码都是正常的,发现#  include <boost/detail/endian.hpp>被注释掉,导致htonll被宏定义为

#define htonll(n) (n)

没有转换为大端字节序


标签:return,double,dub,writeDouble,cast,消息,ENDIAN,序列化,Thrift
From: https://blog.51cto.com/fengyuzaitu/6326615

相关文章

  • python控制微信发消息
    使用pyautogui控制PC版微信,发消息。importpyautoguiimporttimedefOpen_Wechat():#使用快捷键打开微信。这个微信的默认设置的快捷键。pyautogui.hotkey('ctrl','alt','w')time.sleep(1)defChat_Who(ContactPerson):#使用快捷键打开查找,找一个......
  • python实现kafka收到消息然后在通过websockt发送给其他服务器的方法(异步调用并且收到
    importasyncioimportthreadingfromkafkaimportKafkaConsumerimportwebsocketsconnected=set()asyncdefhandler(websocket,path):connected.add(websocket)whileTrue:awaitasyncio.sleep(1)defstart_kafka():consumer=KafkaC......
  • 云原生之使用Docker部署RabbitMQ消息中间件
    (云原生之使用Docker部署RabbitMQ消息中间件一、RabbitMQ介绍1.RabbitMQ简介RabbitMQ是使用Erlang语言来编写的,并且RabbitMQ是基于AMQP协议的。RabbitMQ是一个开源的消息代理的队列服务器,用来通过普通协议在完全不同的应用之间共享数据。2.RabbitMQ特点开源、性能优秀,稳定......
  • dotnet平台Http消息处理者工厂
    1前言Microsoft.Extensions.Http是一个设计非常优异的客户端工厂库,其提供了IHttpClientFactory用于创建HttpClient和IHttpMessageHandlerFactory用于创建HttpMessageHandler。遗憾的是这个库目前仅非常试用于客户端,而不太适用于转发端。我们对客户端的定义是一个软件在某种业务......
  • 微信⼩程序开发消息推送配置教程
    微信⼩程序开发消息推送配置这⼀块⽹上都是PHP居多,由于⽤egg.js写了⼀套验证⽅法。第⼀步:填写服务器配置登录微信⼩程序官⽹后,在⼩程序官⽹的“设置-消息服务器”页⾯,管理员扫码启⽤消息服务,填写服务器地址(URL)、Token和EncodingAESKey。URL是开发者⽤来接收微信消息和事件的接......
  • RocketMQ事务消息原理
    一、RocketMQ事务消息原理:        RocketMQ在4.3版本之后实现了完整的事务消息,基于MQ的分布式事务方案,本质上是对本地消息表的一个封装,整体流程与本地消息表一致,唯一不同的就是将本地消息表存在了MQ内部,而不是业务数据库,事务消息解决的是生产端的消息发送与本地事务执行......
  • 【fastweixin框架教程6】微信企业号给关注的用户主动发送推送消息
     下面这个类我对fastweixin框架的简单封装调用,大家可以参考,如果需要QYAPIConfigExt和MainServernSupport,请参考本教程以前几篇文章  如需测试,需要去微信企业号官网申请试用账号。其中发送文本消息和图文消息都是没有问题。  我们知道,企业号主要......
  • 用redis实现支持优先级的消息队列
    用redis实现支持优先级的消息队列 为什么需要消息队列系统中引入消息队列机制是对系统一个非常大的改善。例如一个web系统中,用户做了某项操作后需要发送邮件通知到用户邮箱中。你可以使用同步方式让用户等待邮件发送完成后反馈给用户,但是这样可能会因为网络的不确定性造成用......
  • drf之APIView+序列化类+Response
    昨日回顾#0ser=BookSerialzier(instance=qs,many=True)---->ListSerializer[序列化对象,序列化对象]ser=BookSerialzier(instance=book)---->BookSerialzier#1定制序列化的字段之source,字段参数 -指定一个要序列化的对象中得字段-指定一个要序列化的对象中得方法,方......
  • 直播源码技术控制直播稳定之消息篇
     在日常生活中,我们上网看直播在各个直播间内通常能看到各种各样的消息,像是用户为主播打赏礼物,直播间聊天区,又或是用户点赞出现的符号信息等,这些消息在让直播间变得多姿多彩同时,也为直播平台运营商面临了一个问题:当消息类型同时发出且数量庞大时,直播间就很可能崩溃,那我们如何解决......