TSimpleServer简单实现Tserver,代码如下。

/**
* Simple singlethreaded server for testing.
*
*/
public class TSimpleServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TSimpleServer.class.getName()); private boolean stopped_ = false; public TSimpleServer(AbstractServerArgs args) {
super(args);
} public void serve() {
stopped_ = false;
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(); // 获得一个client transport
if (client != null) { // 以下代码根据获取的client transport层层封装
processor = processorFactory_.getProcessor(client); // 根据client获取processor
inputTransport = inputTransportFactory_.getTransport(client); // 根据client获取input transport
outputTransport = outputTransportFactory_.getTransport(client); // 根据client获取output transport
inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); // 根据input transport获取input protocol
outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); // 根据output transport获取output protocol
if (eventHandler_ != null) {// 处理前切入eventHandler根据input/output protocol生成connectionContext
connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol);
}
while (true) {// 一直循环处理同一个用户的请求,processor.process永远返回true,只有抛出异常时(即用户端主动关闭连接)才会继续接收下一个用户的请求。
if (eventHandler_ != null) {// 切入eventHandler处理前面生成的connectionContext
eventHandler_.processContext(connectionContext, inputTransport, outputTransport);
}
if(!processor.process(inputProtocol, outputProtocol)) {// 调用processor对input/output protocol进行处理
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);
} public void stop() {
stopped_ = true;
serverTransport_.interrupt();
}
}

首先,开启监听,然后在处理之前面向切面切入前处理流程 eventHandler_.preServe();最后进入接收处理流程。

处理时关键看第54行processor.process()函数。

TProcessor为一单接口,仅含process方法。其子类thrift不再提供,而是根据用户自定义的thrift IDL文件自动生成。然而thrift提供了一个抽象类TBaseProcessor<I>封装了一些常用的实现,该类实现了TProcessor接口,框架自动生成的Processor都继承了该基类。

TBaseProcessor<I>代码如下:

public abstract class TBaseProcessor<I> implements TProcessor {
private final I iface; // 真正的处理函数实现
private final Map<String,ProcessFunction<I, ? extends TBase>> processMap; protected TBaseProcessor(I iface, Map<String, ProcessFunction<I, ? extends TBase>> processFunctionMap) {
this.iface = iface;
this.processMap = processFunctionMap;
} public Map<String,ProcessFunction<I, ? extends TBase>> getProcessMapView() {
return Collections.unmodifiableMap(processMap);
} @Override
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;
}
}

ProcessFunction为一抽象类,其子类也是根据IDL自动生成。与IDL中的函数一一对应,为代理处理器。

TBase为IDL中定义的types的基类。T封装了处理函数的参数信息,其子类也是框架根据IDL自动生成。

public abstract class ProcessFunction<I, T extends TBase> {
private final String methodName; private static final Logger LOGGER = LoggerFactory.getLogger(ProcessFunction.class.getName()); public ProcessFunction(String methodName) {
this.methodName = methodName;
} public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException {
T args = getEmptyArgsInstance(); // 获取一个空的参数封装
try {
args.read(iprot); // 从input protol中读取所有参数到args中
} 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(); // 读取参数完毕
TBase result = null; try {
result = getResult(iface, args); // 获取处理结果
} catch(Throwable th) {
LOGGER.error("Internal error processing " + getMethodName(), th);
TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR,
"Internal error processing " + getMethodName());
oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
x.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
return;
} if(!isOneway()) {// true表示单向操作不许要返回信息,即函数为void类型。false表示需要返回值,则启用output protol写入结果。
oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.REPLY, seqid));
result.write(oprot);
oprot.writeMessageEnd();
oprot.getTransport().flush();
}
} protected abstract boolean isOneway(); public abstract TBase getResult(I iface, T args) throws TException; public abstract T getEmptyArgsInstance(); public String getMethodName() {
return methodName;
}
}

到此为止,基本了解了libthrift的大致框架。在处理函数中主要是与protocol打交道,protocol又是根据input/output transport生成,而input/output transport又是根据client transport生成。总形成三层结构,底层是client transport由server transport的accept函数获得,中层是input/output transport ,顶层是input/output protocol。然而三层之间并不是完全透明不可见的,典型如oprot.getTransport().flush() 对上层暴露了底层,也无伤大雅。

下节介绍protocol以及transport。

libthrift0.9.0解析(二)之TSimpleServer的更多相关文章

  1. libthrift0.9.0解析(四)之TThreadPoolServer&ServerContext

    TThreadPoolServer直接继承自TServer,实现类serve和stop操作. 在serve中可以接受多个连接,每个连接单独开一个线程进行处理,在每个线程中,按顺序处理该线程所绑定连接的 ...

  2. libthrift0.9.0解析(三)之TProtocol&TTransport

       以上是transport和protocol的类图和结构图. transport封装了底层的传输通道,主要有read/write.open/close等基本的读写方法,而且都是对于二进制数据. p ...

  3. libthrift0.9.0解析(五)之TNonblockingServer&THsHaServer

    本文是一边看代码一边写的,是真随笔,随看随下笔. 看TNonblockingServer,先看其父类AbstractNonblockingServer.一般来说,父类封装的都是通用的东西,具体的底层实 ...

  4. libthrift0.9.0解析(一)之TServer

    TServer 属性serverTransport 为TServerTransport类型,类图如下: 构造函数,简单根据args设置几个成员,大部分是工厂类: protected TServer(A ...

  5. Fixflow引擎解析(二)(模型) - BPMN2.0读写

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  6. C#使用zxing,zbar,thoughtworkQRcode解析二维码,附源代码

    最近做项目需要解析二维码图片,找了一大圈,发现没有人去整理下开源的几个库案例,花了点时间 做了zxing,zbar和thoughtworkqrcode解析二维码案例,希望大家有帮助. zxing是谷歌 ...

  7. Java生成与解析二维码

    1.下载支持二维码的jar包qrcode.jar和qrcode_swetake.jar, 其中qrcode_swetake.jar用于生成二维码,rcode.jar用于解析二维码,jar包下载地址(免 ...

  8. java 生成和解析二维码

    public class QRCode { /** * 解析二维码(QRCode) * @param imgPath * @return */ public static String decoder ...

  9. java代码生成二维码以及解析二维码

    package com.test; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedI ...

随机推荐

  1. C++学习笔记7——模板

    函数模板: #include <iostream> using namespace std; template <typename T> T max(const T & ...

  2. 使用bootstrap模态框实现浮动层

    authour: 陈博益 updatetime: 2015-04-22 06:52:15 friendly link: http://v3.bootcss.com/javascript/#modals ...

  3. (转) IsPostBack的用法

    某一天在网上看到有人写了这样一段代码: protected void Page_Load(object sender, EventArgs e)     {         if (!IsPostBa ...

  4. Android中AsyncTask异步

    今天我们学习了 AsyncTack, 这是一个异步任务. 那么这个异步任务可以干什么呢? 因为只有UI线程,即主线程可以对控件进行更新操作.好处是保证UI稳定性,避免多线程对UI同时操作. 同时要把耗 ...

  5. poj 1066 Treasure Hunt

    http://poj.org/problem?id=1066 #include <cstdio> #include <cstring> #include <cmath&g ...

  6. C51 延时程序

    一.相关换算 1.1s=10^3ms(毫秒)=10^6μs(微秒)=10^9ns(纳秒)=10^12ps(皮秒)=10^15fs(飞秒)=10^18as(阿秒)=10^21zm(仄秒)=10^24ym ...

  7. 前端问题——png图片在IE6下透明失效,解决办法

    今天,一位同事问我问题,png 图片在IE6下透明背景失效. 解决办法,在网上查了很多,最后还是采用两种方案来解决这个问题 1.把这个网页的png格式图片变更为gif格式的图片.问题解决 2.就是让这 ...

  8. ArcGis : unable to save as template this document is already based on another template

    原文:http://forums.esri.com/Thread.asp?c=93&f=989&t=289930 ----------------- I ran into this p ...

  9. SRM468 - SRM469(1-250pt, 500pt)

    SRM 468 DIV1 250pt 题意:给出字典,按照一定要求进行查找. 解法:模拟题,暴力即可. tag:water score: 0.... 这是第一次AC的代码: /* * Author: ...

  10. MyBatis(1):MyBatis入门

    MyBatis是什么 MyBatis是什么,MyBatis的jar包中有它的官方文档,文档是这么描述MyBatis的: MyBatis is a first class persistence fra ...