从(四)server代码跟进

  1. public static void simple(MultiplicationService.Processor processor) {
  2. try {
  3. TServerTransport serverTransport = new TServerSocket(9090);
  4. TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
  5.  
  6. System.out.println("Starting the simple server...");
  7. server.serve();
  8. } catch (Exception e) {
  9. e.printStackTrace();
  10. }
  11. }

跟进server.serve()

  1. public void serve() {
  2. try {
  3. serverTransport_.listen();
  4. } catch (TTransportException ttx) {
  5. LOGGER.error("Error occurred during listening.", ttx);
  6. return;
  7. }
  8.  
  9. // Run the preServe event
  10. if (eventHandler_ != null) {
  11. eventHandler_.preServe();
  12. }
  13.  
  14. setServing(true);
  15.  
  16. while (!stopped_) {
  17. TTransport client = null;
  18. TProcessor processor = null;
  19. TTransport inputTransport = null;
  20. TTransport outputTransport = null;
  21. TProtocol inputProtocol = null;
  22. TProtocol outputProtocol = null;
  23. ServerContext connectionContext = null;
  24. try {
  25. client = serverTransport_.accept();
  26. if (client != null) {
  27. processor = processorFactory_.getProcessor(client);
  28. inputTransport = inputTransportFactory_.getTransport(client);
  29. outputTransport = outputTransportFactory_.getTransport(client);
  30. inputProtocol = inputProtocolFactory_.getProtocol(inputTransport);
  31. outputProtocol = outputProtocolFactory_.getProtocol(outputTransport);
  32. if (eventHandler_ != null) {
  33. connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
  34. }
  35. while (true) {
  36. if (eventHandler_ != null) {
  37. eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
  38. }
  39. if(!processor.process(inputProtocol, outputProtocol)) {
  40. break;
  41. }
  42. }
  43. }
  44. } catch (TTransportException ttx) {
  45. // Client died, just move on
  46. } catch (TException tx) {
  47. if (!stopped_) {
  48. LOGGER.error("Thrift error occurred during processing of message.", tx);
  49. }
  50. } catch (Exception x) {
  51. if (!stopped_) {
  52. LOGGER.error("Error occurred during processing of message.", x);
  53. }
  54. }
  55.  
  56. if (eventHandler_ != null) {
  57. eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol);
  58. }
  59.  
  60. if (inputTransport != null) {
  61. inputTransport.close();
  62. }
  63.  
  64. if (outputTransport != null) {
  65. outputTransport.close();
  66. }
  67.  
  68. }
  69. setServing(false);
  70. }

跟进accept方法

  1. protected TSocket acceptImpl() throws TTransportException {
  2. if (serverSocket_ == null) {
  3. throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket.");
  4. }
  5. try {
  6. Socket result = serverSocket_.accept();
  7. TSocket result2 = new TSocket(result);
  8. result2.setTimeout(clientTimeout_);
  9. return result2;
  10. } catch (IOException iox) {
  11. throw new TTransportException(iox);
  12. }
  13. }

由于(四)使用的是阻塞IO, 代码也可以看到阻塞直到有客户端连接

跟进process()方法

  1. public boolean process(TProtocol in, TProtocol out) throws TException {
  2. TMessage msg = in.readMessageBegin();
  3. ProcessFunction fn = processMap.get(msg.name);
  4. if (fn == null) {
  5. TProtocolUtil.skip(in, TType.STRUCT);
  6. in.readMessageEnd();
  7. TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'");
  8. out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));
  9. x.write(out);
  10. out.writeMessageEnd();
  11. out.getTransport().flush();
  12. return true;
  13. }
  14. fn.process(msg.seqid, in, out, iface);
  15. return true;
  16. }

整体流程,readMessageBegin读客户端请求方法。请求方法在服务端没有注册,返回异常给客户端。如果有方法,对应方法处理。跟进process方法

  1. public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
  2. T args = getEmptyArgsInstance();
  3. try {
  4. args.read(iprot);
  5. } catch (TProtocolException e) {
  6. iprot.readMessageEnd();
  7. TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());
  8. oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
  9. x.write(oprot);
  10. oprot.writeMessageEnd();
  11. oprot.getTransport().flush();
  12. return;
  13. }
  14. iprot.readMessageEnd();
  15. TSerializable result = null;
  16. byte msgType = TMessageType.REPLY;
  17.  
  18. try {
  19. result = getResult(iface, args);
  20. } catch (TTransportException ex) {
  21. LOGGER.error("Transport error while processing " + getMethodName(), ex);
  22. throw ex;
  23. } catch (TApplicationException ex) {
  24. LOGGER.error("Internal application error processing " + getMethodName(), ex);
  25. result = ex;
  26. msgType = TMessageType.EXCEPTION;
  27. } catch (Exception ex) {
  28. LOGGER.error("Internal error processing " + getMethodName(), ex);
  29. if(!isOneway()) {
  30. result = new TApplicationException(TApplicationException.INTERNAL_ERROR,
  31. "Internal error processing " + getMethodName());
  32. msgType = TMessageType.EXCEPTION;
  33. }
  34. }
  35.  
  36. if(!isOneway()) {
  37. oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
  38. result.write(oprot);
  39. oprot.writeMessageEnd();
  40. oprot.getTransport().flush();
  41. }
  42. }

跟进读取参数方法

  1. public void read(org.apache.thrift.protocol.TProtocol iprot, multiply_args struct) throws org.apache.thrift.TException {
  2. org.apache.thrift.protocol.TField schemeField;
  3. iprot.readStructBegin();
  4. while (true)
  5. {
  6. schemeField = iprot.readFieldBegin();
  7. if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
  8. break;
  9. }
  10. switch (schemeField.id) {
  11. case 1: // N1
  12. if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
  13. struct.n1 = iprot.readI32();
  14. struct.setN1IsSet(true);
  15. } else {
  16. org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
  17. }
  18. break;
  19. case 2: // N2
  20. if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
  21. struct.n2 = iprot.readI32();
  22. struct.setN2IsSet(true);
  23. } else {
  24. org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
  25. }
  26. break;
  27. default:
  28. org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
  29. }
  30. iprot.readFieldEnd();
  31. }
  32. iprot.readStructEnd();
  33.  
  34. // check for required fields of primitive type, which can't be checked in the validate method
  35. struct.validate();
  36. }

服务端跟进处理

  1. result = getResult(iface, args);

继续跟进

  1. public multiply_result getResult(I iface, multiply_args args) throws org.apache.thrift.TException {
  2. multiply_result result = new multiply_result();
  3. result.success = iface.multiply(args.n1, args.n2);
  4. result.setSuccessIsSet(true);
  5. return result;
  6. }

这里拿到结果, 最后写回给客户端

  1. if(!isOneway()) {
  2. oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid));
  3. result.write(oprot);
  4. oprot.writeMessageEnd();
  5. oprot.getTransport().flush();
  6. }

这是最简单的一种方式,使用阻塞io, 二进制协议序列化。还有分阻塞, 压缩协议等。

Thrift笔记(五)--Thrift server源码分析的更多相关文章

  1. 转载-FileZilla Server源码分析(1)

    FileZilla Server源码分析(1) 分类: VC 2012-03-27 17:32 2363人阅读 评论(0) 收藏 举报 serversocketftp服务器usersockets工作 ...

  2. Flask框架(五) —— session源码分析

    Flask框架(五) —— session源码分析 目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = s ...

  3. Appium Server源码分析之作为Bootstrap客户端

    Appium Server拥有两个主要的功能: 它是个http服务器,它专门接收从客户端通过基于http的REST协议发送过来的命令 他是bootstrap客户端:它接收到客户端的命令后,需要想办法把 ...

  4. Appium Server 源码分析之启动运行Express http服务器

    通过上一个系列Appium Android Bootstrap源码分析我们了解到了appium在安卓目标机器上是如何通过bootstrap这个服务来接收appium从pc端发送过来的命令,并最终使用u ...

  5. Java源码解析——集合框架(五)——HashMap源码分析

    HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...

  6. Nginx学习笔记(四) 源码分析&socket/UDP/shmem

    源码分析 在茫茫的源码中,看到了几个好像挺熟悉的名字(socket/UDP/shmem).那就来看看这个文件吧!从简单的开始~~~ src/os/unix/Ngx_socket.h&Ngx_s ...

  7. Nginx学习笔记(六) 源码分析&启动过程

    Nginx的启动过程 主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码: /* * ...

  8. Java并发编程笔记之Semaphore信号量源码分析

    JUC 中 Semaphore 的使用与原理分析,Semaphore 也是 Java 中的一个同步器,与 CountDownLatch 和 CycleBarrier 不同在于它内部的计数器是递增的,那 ...

  9. 【Java入门提高篇】Day22 Java容器类详解(五)HashMap源码分析(上)

    准备了很长时间,终于理清了思路,鼓起勇气,开始介绍本篇的主角——HashMap.说实话,这家伙能说的内容太多了,要是像前面ArrayList那样翻译一下源码,稍微说说重点,肯定会让很多人摸不着头脑,不 ...

随机推荐

  1. [AGC006] D - Median Pyramid Hard 二分

    Description ​ 现在有一个NN层的方块金字塔,从最顶层到最底层分别标号为1...N1...N. ​ 第ii层恰好有2i−12i−1个方块,且每一层的中心都是对齐的. 这是一个N=4N=4的 ...

  2. python操作RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  3. 大型php网站性能和并发访问优化方案(转载自php中文网)

               网站性能优化对于大型网站来说非常重要,一个网站的访问打开速度影响着用户体验度,网站访问速度慢会造成高跳出率,小网站很好解决,那对于大型网站由于栏目多,图片和图像都比较庞大,那该怎 ...

  4. 百度地图中使用mouseover事件获取经纬度时无法拿到鼠标所在位置的经纬度。

    用百度2.0的话使用mousemove 鼠标在地图区域移动过程中触发此事件.mouseover参数e中没有point参数

  5. python基础01—基础数据类型

    数据类型 单位换算 最小的单位为bit,表示一个二进制的0或1,一般使用小写的b表示 存储的最小单位为字节(Byte),1B = 8b 1024B = 1KB 1024KB = 1MB 1024MB ...

  6. Navicat 连接Sqlite数据库的方法和步骤

    1.打开Navicat,进行如下操作. 2.在弹出的新建连接对话框中输入正确的信息,点击“确定”按钮. 3.可见如下

  7. GCD(最大公约数)和LCM(最小公倍数)的求法

    GCD(最大公约数) (1)辗转相除法(欧几里得算法)(常用) 将两个数a, b相除,如果余数c不等于0,就把b的值给a,c的值给b,直到c等于0,此时最大公约数就是b (2)更相减损术 将两个书中较 ...

  8. [BZOJ 5415] 归程

    一棵KrusKal重构树,然而我数组开小了,忘记清空一个标记 洛谷传送门 BZOJ传送门 ......好像成权限题了Orz 回顾我们用KrusKal做生成树的时候,我们将边排序后连通各个连通块,那么边 ...

  9. 洛谷 P2059 [JLOI2013]卡牌游戏(概率dp)

    题面 洛谷 题解 \(f[i][j]\)表示有i个人参与游戏,从庄家(即1)数j个人获胜的概率是多少 \(f[1][1] = 1\) 这样就可以不用讨论淘汰了哪些人和顺序 枚举选庄家选那张牌, 枚举下 ...

  10. Spring对外部属性文件指定的某个属性进行加密、解密

    [From] http://blog.csdn.net/ethanq/article/details/7333897 在我们开发当中,经常会用到spring框架来读取属性文件的属性值,然后使用占位符引 ...