Thrift笔记(五)--Thrift server源码分析
从(四)server代码跟进
- public static void simple(MultiplicationService.Processor processor) {
- try {
- TServerTransport serverTransport = new TServerSocket(9090);
- TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
- System.out.println("Starting the simple server...");
- server.serve();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
跟进server.serve()
- public void serve() {
- try {
- serverTransport_.listen();
- } catch (TTransportException ttx) {
- LOGGER.error("Error occurred during listening.", ttx);
- return;
- }
- // Run the preServe event
- if (eventHandler_ != null) {
- eventHandler_.preServe();
- }
- setServing(true);
- while (!stopped_) {
- TTransport client = null;
- TProcessor processor = null;
- TTransport inputTransport = null;
- TTransport outputTransport = null;
- TProtocol inputProtocol = null;
- TProtocol outputProtocol = null;
- ServerContext connectionContext = null;
- try {
- client = serverTransport_.accept();
- if (client != null) {
- processor = processorFactory_.getProcessor(client);
- inputTransport = inputTransportFactory_.getTransport(client);
- outputTransport = outputTransportFactory_.getTransport(client);
- inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
- outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
- if (eventHandler_ != null) {
- connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
- }
- while (true) {
- if (eventHandler_ != null) {
- eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
- }
- if(!processor.process(inputProtocol, outputProtocol)) {
- break;
- }
- }
- }
- } catch (TTransportException ttx) {
- // Client died, just move on
- } catch (TException tx) {
- if (!stopped_) {
- LOGGER.error("Thrift error occurred during processing of message.", tx);
- }
- } catch (Exception x) {
- if (!stopped_) {
- LOGGER.error("Error occurred during processing of message.", x);
- }
- }
- if (eventHandler_ != null) {
- eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol);
- }
- if (inputTransport != null) {
- inputTransport.close();
- }
- if (outputTransport != null) {
- outputTransport.close();
- }
- }
- setServing(false);
- }
跟进accept方法
- protected TSocket acceptImpl() throws TTransportException {
- if (serverSocket_ == null) {
- throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket.");
- }
- try {
- Socket result = serverSocket_.accept();
- TSocket result2 = new TSocket(result);
- result2.setTimeout(clientTimeout_);
- return result2;
- } catch (IOException iox) {
- throw new TTransportException(iox);
- }
- }
由于(四)使用的是阻塞IO, 代码也可以看到阻塞直到有客户端连接
跟进process()方法
- public boolean process(TProtocol in, TProtocol out) throws TException {
- TMessage msg = in.readMessageBegin();
- ProcessFunction fn = processMap.get(msg.name);
- if (fn == null) {
- TProtocolUtil.skip(in, TType.STRUCT);
- in.readMessageEnd();
- TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
- out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
- x.write(out);
- out.writeMessageEnd();
- out.getTransport().flush();
- return true;
- }
- fn.process(msg.seqid, in, out, iface);
- return true;
- }
整体流程,readMessageBegin读客户端请求方法。请求方法在服务端没有注册,返回异常给客户端。如果有方法,对应方法处理。跟进process方法
- public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
- T args = getEmptyArgsInstance();
- try {
- args.read(iprot);
- } catch (TProtocolException e) {
- iprot.readMessageEnd();
- TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
- oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
- x.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
- return;
- }
- iprot.readMessageEnd();
- TSerializable result = null;
- byte msgType = TMessageType.REPLY;
- try {
- result = getResult(iface, args);
- } catch (TTransportException ex) {
- LOGGER.error("Transport error while processing " + getMethodName(), ex);
- throw ex;
- } catch (TApplicationException ex) {
- LOGGER.error("Internal application error processing " + getMethodName(), ex);
- result = ex;
- msgType = TMessageType.EXCEPTION;
- } catch (Exception ex) {
- LOGGER.error("Internal error processing " + getMethodName(), ex);
- if(!isOneway()) {
- result = new TApplicationException(TApplicationException.INTERNAL_ERROR,
- "Internal error processing " + getMethodName());
- msgType = TMessageType.EXCEPTION;
- }
- }
- if(!isOneway()) {
- oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
- result.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
- }
- }
跟进读取参数方法
- public void read(org.apache.thrift.protocol.TProtocol iprot, multiply_args struct) throws org.apache.thrift.TException {
- org.apache.thrift.protocol.TField schemeField;
- iprot.readStructBegin();
- while (true)
- {
- schemeField = iprot.readFieldBegin();
- if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
- break;
- }
- switch (schemeField.id) {
- case 1: // N1
- if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
- struct.n1 = iprot.readI32();
- struct.setN1IsSet(true);
- } else {
- org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
- }
- break;
- case 2: // N2
- if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
- struct.n2 = iprot.readI32();
- struct.setN2IsSet(true);
- } else {
- org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
- }
- break;
- default:
- org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
- }
- iprot.readFieldEnd();
- }
- iprot.readStructEnd();
- // check for required fields of primitive type, which can't be checked in the validate method
- struct.validate();
- }
服务端跟进处理
- result = getResult(iface, args);
继续跟进
- public multiply_result getResult(I iface, multiply_args args) throws org.apache.thrift.TException {
- multiply_result result = new multiply_result();
- result.success = iface.multiply(args.n1, args.n2);
- result.setSuccessIsSet(true);
- return result;
- }
这里拿到结果, 最后写回给客户端
- if(!isOneway()) {
- oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
- result.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
- }
这是最简单的一种方式,使用阻塞io, 二进制协议序列化。还有分阻塞, 压缩协议等。
Thrift笔记(五)--Thrift server源码分析的更多相关文章
- 转载-FileZilla Server源码分析(1)
FileZilla Server源码分析(1) 分类: VC 2012-03-27 17:32 2363人阅读 评论(0) 收藏 举报 serversocketftp服务器usersockets工作 ...
- Flask框架(五) —— session源码分析
Flask框架(五) —— session源码分析 目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = s ...
- Appium Server源码分析之作为Bootstrap客户端
Appium Server拥有两个主要的功能: 它是个http服务器,它专门接收从客户端通过基于http的REST协议发送过来的命令 他是bootstrap客户端:它接收到客户端的命令后,需要想办法把 ...
- Appium Server 源码分析之启动运行Express http服务器
通过上一个系列Appium Android Bootstrap源码分析我们了解到了appium在安卓目标机器上是如何通过bootstrap这个服务来接收appium从pc端发送过来的命令,并最终使用u ...
- Java源码解析——集合框架(五)——HashMap源码分析
HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...
- Nginx学习笔记(四) 源码分析&socket/UDP/shmem
源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_socket.h&Ngx_s ...
- Nginx学习笔记(六) 源码分析&启动过程
Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...
- Java并发编程笔记之Semaphore信号量源码分析
JUC 中 Semaphore 的使用与原理分析,Semaphore 也是 Java 中的一个同步器,与 CountDownLatch 和 CycleBarrier 不同在于它内部的计数器是递增的,那 ...
- 【Java入门提高篇】Day22 Java容器类详解(五)HashMap源码分析(上)
准备了很长时间,终于理清了思路,鼓起勇气,开始介绍本篇的主角——HashMap.说实话,这家伙能说的内容太多了,要是像前面ArrayList那样翻译一下源码,稍微说说重点,肯定会让很多人摸不着头脑,不 ...
随机推荐
- [AGC006] D - Median Pyramid Hard 二分
Description 现在有一个NN层的方块金字塔,从最顶层到最底层分别标号为1...N1...N. 第ii层恰好有2i−12i−1个方块,且每一层的中心都是对齐的. 这是一个N=4N=4的 ...
- python操作RabbitMQ、Redis、Memcache、SQLAlchemy
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
- 大型php网站性能和并发访问优化方案(转载自php中文网)
网站性能优化对于大型网站来说非常重要,一个网站的访问打开速度影响着用户体验度,网站访问速度慢会造成高跳出率,小网站很好解决,那对于大型网站由于栏目多,图片和图像都比较庞大,那该怎 ...
- 百度地图中使用mouseover事件获取经纬度时无法拿到鼠标所在位置的经纬度。
用百度2.0的话使用mousemove 鼠标在地图区域移动过程中触发此事件.mouseover参数e中没有point参数
- python基础01—基础数据类型
数据类型 单位换算 最小的单位为bit,表示一个二进制的0或1,一般使用小写的b表示 存储的最小单位为字节(Byte),1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB ...
- Navicat 连接Sqlite数据库的方法和步骤
1.打开Navicat,进行如下操作. 2.在弹出的新建连接对话框中输入正确的信息,点击“确定”按钮. 3.可见如下
- GCD(最大公约数)和LCM(最小公倍数)的求法
GCD(最大公约数) (1)辗转相除法(欧几里得算法)(常用) 将两个数a, b相除,如果余数c不等于0,就把b的值给a,c的值给b,直到c等于0,此时最大公约数就是b (2)更相减损术 将两个书中较 ...
- [BZOJ 5415] 归程
一棵KrusKal重构树,然而我数组开小了,忘记清空一个标记 洛谷传送门 BZOJ传送门 ......好像成权限题了Orz 回顾我们用KrusKal做生成树的时候,我们将边排序后连通各个连通块,那么边 ...
- 洛谷 P2059 [JLOI2013]卡牌游戏(概率dp)
题面 洛谷 题解 \(f[i][j]\)表示有i个人参与游戏,从庄家(即1)数j个人获胜的概率是多少 \(f[1][1] = 1\) 这样就可以不用讨论淘汰了哪些人和顺序 枚举选庄家选那张牌, 枚举下 ...
- Spring对外部属性文件指定的某个属性进行加密、解密
[From] http://blog.csdn.net/ethanq/article/details/7333897 在我们开发当中,经常会用到spring框架来读取属性文件的属性值,然后使用占位符引 ...