前言

因为工作上需要开发一款C/S架构的软件, 在客户端和服务器之间通信方式上, 经过几番思考之后决定采用thrift 库作为通信工具.

thrift 库的设计理念

thrift库的调用采用的函数接口的方式, 设计者设计之初希望将网络传输层, 和数据协议层彻底隔离. 网络通信的使用如同在本地调用一样. 这种设计理念是非常惊艳的. 让开发者更加专注于业务逻辑上. 这也意味着thrift 库的 同步调用将成主流. 对于网络通信而言, 同步通信曾经是挥之不去的噩梦. 但是thrift 却提供了一种非常优雅的方式处理: 将所有网络通信问题封装成异常.

thrift 开发常见问题

thrift 身份认知机制

thrift 本身并没有提供身份识别机制. 服务器本身无法自动识别客户端身份. 开发者如果需要实现身份识别机制, 则需要在每个接口函数上提供身份识别ID. 
例如: sayHi(const string t_ssid ); 
t_ssid 即为身份识别ID. ssid 在客户端第一次连接服务器时, 由服务器生成的特定字符串特征码. 客户端和服务端各存一份. 客户端向服务端申请服务时 服务端即可根据客户端所提供的ID 信息, 选择是否提供服务.

大数据传输

thrift 库本身支持常用基础的类型, 数据结构, 类为了实现大数据量的传输, 例如需要将一张数据库表传输出去, 单纯使用数据结构是非常糟糕的. 这时候就必须考虑数据序列化的处理方式. 例如将一个类的数据全部转化成 json 格式的string进行传输. 
笔者做过一个基本的测试, 将size为10W 的string类型传输到服务器,在回传到客户端 , thrift 均可以完全胜任

主动抛出异常

由于thrift接口不支持引用,或者指针, 接口层仅接受一个参数作为返回值. 由于返回参数本身需要负责数据的传输工作, 将错误信息通过返回参数方式显然太过奢侈.同时也将大大增加编程的复杂程度. 由于thrift 支持用户自定义异常, 对于可使用主动抛出异常的方式来传输错误信息.

接口异常被动保护机制

由于thrift 每次在返回前都会捕获异常. 用户自定义异常放行. 其他异常将主动捕捉,并且报错. 报错后服务器将对当前客户端连接拒绝服务器, 甚至导致整个thift 服务器服务器卡死的情况发生. 这也就要求开发者在服务器端要求有着严格的异常保护机制. 由于thrift服务器异常错误将无法提供错误触发原因. 将导致软件异常难以调试. 笔者的做法是在thrift层执行 std::exception 异常捕获. 主动将所有非用户自定义异常捕获, 并且将程序 abort()掉.以方便快速定位软件错误.

客户端多线程保护机制

客户端的thrift 客户端调用本身不具备多线程的保护机制. 在客户端使用多线程通信时, 开发者需要使用多线程保护机制. 否则服务器非常容易被客户端引发异常错误. 导致拒绝服务

C++ 兼容XP 系统

由于thrift 默认使用了WIN7 的网络通信库, 导致thrift无法兼容XP. 笔者使用的thrift 0.9.2 版本库, 在XP 下运行时, 系统提示无法定位 WS2_32.dll , 经过多番讨论和源码研究之后, 发现这是官方的一个bug所致. 之前也有很多人提及到这个bug的存在, 但是因为国外 XP的覆盖率太低, 这个bug 到thrift 0.9.3 均未解决.

thrift 兼容XP 系统的解决方案

首先定位thrift源码中的 
thrift-0.9.2\lib\cpp\src\thrift\windows\WinFcntl.cpp 
此文件根据系统的版本的不同, 定义不同的网络通信方案. 通过源码可得知,其实官方的thrift在开发之初是有直接支持XP 系统的, 只是因为bug 的原因, 所有的系统均调用了 
* WSAPoll(fdArray, nfds, timeout);* 这个函数, 导致软件无法在XP运行. 
既然知道了这个原因, 从最小修改代码的角度出发, 既然thrift 源码无法对系统 _WIN32_WINNT 有效的识别, 那么直接强制thrift 均采用 XP 模式下的网络通信方案,即可解决兼容XP 的问题

/// 需要屏蔽此行
#if _WIN32_WINNT <= 0x0502 //XP, Server2003
/// 需要屏蔽此行
int thrift_poll(THRIFT_POLLFD *fdArray, ULONG nfds, INT timeout)
{fd_set read_fds, write_fds;fd_set* read_fds_ptr  = NULL;fd_set* write_fds_ptr = NULL;FD_ZERO(&read_fds);FD_ZERO(&write_fds);for(ULONG i=0; i<nfds; i++) {//Read (in) socketif((fdArray[i].events & THRIFT_POLLIN) == THRIFT_POLLIN) {read_fds_ptr = &read_fds;FD_SET(fdArray[i].fd, &read_fds);}//Write (out) socketelse if((fdArray[i].events & THRIFT_POLLOUT) == THRIFT_POLLOUT) {write_fds_ptr = &write_fds;FD_SET(fdArray[i].fd, &write_fds);}}timeval time_out;timeval* time_out_ptr = NULL;if(timeout >= 0) {timeval time_out = {timeout / 1000, (timeout % 1000) * 1000};time_out_ptr = &time_out;}else { //to avoid compiler warnings(void)time_out;(void)timeout;}int sktready = select(1, read_fds_ptr, write_fds_ptr, NULL, time_out_ptr);if(sktready > 0) {for(ULONG i=0; i<nfds; i++) {fdArray[i].revents = 0;if(FD_ISSET(fdArray[i].fd, &read_fds))fdArray[i].revents |= THRIFT_POLLIN;if(FD_ISSET(fdArray[i].fd, &write_fds))fdArray[i].revents |= THRIFT_POLLOUT;}}return sktready;
}//// 需要屏蔽 , 此宏定义根据系统版本采用不同的通信机制
#else //Vista, Win7...
int thrift_poll(THRIFT_POLLFD *fdArray, ULONG nfds, INT timeout)
{return WSAPoll(fdArray, nfds, timeout);
}
#endif // WINVER
//// 需要屏蔽
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

兼容性方案总结

通过屏蔽以上几行代码, 亲测可实现兼容XP 的功能. 但是听大神提示说, XP 模式下的网络效率 比 采用 WIN7 WSAPoll(fdArray, nfds, timeout); 系统库的效率要低. 毕竟XP 是2000年的产品.

通过探讨交流, 有大神提出在现有的基础直接采用boost 网络库的方案, 以解决通信效率的问题.

int thrift_poll(THRIFT_POLLFD *fdArray, ULONG nfds, INT timeout)
{  fd_set read_fds;  fd_set write_fds;  fd_set except_fds;  FD_ZERO(&read_fds);  FD_ZERO(&write_fds);  FD_ZERO(&except_fds);  FD_SET(fdArray[0].fd, &read_fds);  FD_SET(fdArray[0].fd, &write_fds);  FD_SET(fdArray[0].fd, &except_fds);  timeval time_out = {timeout * 0.001, timeout * 1000};  // 下列select库为boost网络库return select(1, &read_fds, &write_fds, &except_fds, &time_out);
}    

WIN-thrift 库 兼容XP系统相关推荐

  1. curl+openssl,编译win32 兼容xp系统的静态库

    版本:openssl-1.0.2n 版本:curl-7.46.0 说明:请通过curl官网获取curl所支持的openssl版本(https://curl.haxx.se/) 1.编译openssl静 ...

  2. win xp java下载,Win雨林木风xp系统Java配置环境变量的方法

    谈起Java环境变量我想大多数编程人员都知道,因为我们想要进行编程就必须先配置它,不过不少用户不知道Win雨林木风xp系统Java怎么配置环境变量,为此雨林木风系统小编赶紧整理了一篇Win雨林木风xp ...

  3. Qtmultimedia库在xp系统无法使用摄像头设备问题解决办法

    当QtMultimedia的QCamera类在XP系统无法获取到摄像头设备,需要重新修改编译qtmultimedia库,将编译生成的dsengine.dll文件替换原来的dsengine.dll库文件 ...

  4. 关于python在64位机器上打包32位exe(兼容xp系统)解决方法

    python在64位机器上打包32位exe 1.下载32位python 3.4.4及以下版本支持xp,32位3.4.4下载地址https://www.python.org/ftp/python/3.4 ...

  5. vs2015 QT5.6 兼容xp系统

    说明: Qt5目前有两个长期支持版本(Long Term Support)Qt5.6和Qt5.9: Qt从5.7版本及以后不再支持WinXP系统,即编译生成的exe文件无法在WinXP系统运行,若要支 ...

  6. Visual Studio 2015安装的Visual Studio Installer生成的msi兼容XP系统

    安装程序开始画在xp显示: 追踪故障源的方法--命令行安装.msi程序,可以看到log日志.即 msiexec /i a.msi /l*v a.log 将会生成名为"a.log"的 ...

  7. VS2019和boost编译支持xp系统

    前言 ​ 最近要做个守护程序来监听一个http程序,故想到了windows的服务程序.因为大量用户使用xp系统,所以要兼容xp. ​ 我用的是vs2019和boost库.两个都需要设置,才能保证程序在 ...

  8. thrift 库使用心得

    前言 thrift 库的设计理念 thrift 开发常见问题 thrift 身份认知机制 大数据传输 主动抛出异常 接口异常被动保护机制 客户端多线程保护机制 C 兼容XP 系统 thrift 兼容X ...

  9. 现在很多单位有用计算机,为什么到了现在,还有很多的单位在用着xp系统?

    xp系统可以说是一款非常经典的系统了,在微软还没有单方面放弃它的时候,它是大多数电脑用户的最爱.而就算是在2014年,微软宣布放弃了xp的更新维护之后,依然还有一些人在坚持使用xp系统. 但随着时间的 ...

最新文章

  1. Python Module_Socket_网络编程
  2. h5-16-SVG 与 HTML5 的 canvas 各自特点
  3. 《Effective Java2》笔录
  4. 安装ubuntu 13.04
  5. Yii获取指定URL路径字符串
  6. 机器学习(二十八)——Monte-Carlo
  7. OC开发_Storyboard——绘制和视图
  8. 两道考研算法设计题- 2010 2013
  9. 移植 libuv 到 Visual C++ 6.0 并支持在 Windows XP 系统下编译
  10. linux+ipv6免流量下载,如何限定apt-get使用IPv4或IPv6协议下载
  11. 订单可视化2实战-生产交付流程(流程再造核心区)
  12. Android集成环信IM,实现聊天置顶功能
  13. 行情真的残酷,3年工龄老员工被毕业生“薪资倒挂”
  14. CSS选择器(select)
  15. jwt-auth官方文档
  16. 使用 jodd:form tag
  17. pyqt5以及pyqtgraph(pyqt界面设计绘图)
  18. PyQt(Python+Qt)学习随笔:树型部件QTreeWidget中当前列currentColumn和选中项selectedItems访问方法
  19. ExcelVBA实现一键生成word文字报告及批量操作[原创]
  20. 今日金融词汇---新股限购,是什么?

热门文章

  1. 个人博客项目开发总结(一) 项目架构及后端开发
  2. arx程序说明(三)
  3. java倒计时三种简单实现方式
  4. js 原生弹框post接口提示
  5. Java字符串替换指定位置的字符
  6. Android studio 一键清除所有断点
  7. BZOJ3834: [Poi2014]Solar Panels
  8. SAP外向交货中的包装功能
  9. Java集合中元素删除
  10. php+mysql+php沿河农产品特卖网站的设计与实现 毕业设计-附源码201524