1. 简介

thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎。以构建在
C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。

2. 下载与安装


Thrift眼下最高0.9.2,地址:http://archive.apache.org/dist/thrift/

注意,我们要把exe和tar文件都下载下来,exe用来编译你的thrift中间语言。而tar解压后,我们能够看到csharp,php,java,js等多种开发语言的实例代码,对我们非常有帮助的,下载最新版。当中包括lib文件库。包括各种语言须要的类库。

下载之后,我们把exe文件可放在C盘,建个Thrift文件夹,把它放入。然后能够配置一下环境变量;将thrift的文件夹路径加入到path变量中;

3. 编写thrift文件


首先编写:tutorial.thrift
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/ # Thrift Tutorial
# Mark Slee (mcslee@facebook.com)
#
# This file aims to teach you how to use Thrift, in a .thrift file. Neato. The
# first thing to notice is that .thrift files support standard shell comments.
# This lets you make your thrift file executable and include your Thrift build
# step on the top line. And you can place comments like this anywhere you like.
#
# Before running this file, you will need to have installed the thrift compiler
# into /usr/local/bin. /**
* The first thing to know about are types. The available types in Thrift are:
*
* bool Boolean, one byte
* byte Signed byte
* i16 Signed 16-bit integer
* i32 Signed 32-bit integer
* i64 Signed 64-bit integer
* double 64-bit floating point value
* string String
* binary Blob (byte array)
* map<t1,t2> Map from one type to another
* list<t1> Ordered list of one type
* set<t1> Set of unique elements of one type
*
* Did you also notice that Thrift supports C style comments? */ // Just in case you were wondering... yes. We support simple C comments too. /**
* Thrift files can reference other Thrift files to include common struct
* and service definitions. These are found using the current path, or by
* searching relative to any paths specified with the -I compiler flag.
*
* Included objects are accessed using the name of the .thrift file as a
* prefix. i.e. shared.SharedObject
*/
include "shared.thrift" /**
* Thrift files can namespace, package, or prefix their output in various
* target languages.
*/
namespace cpp tutorial
namespace d tutorial
namespace java tutorial
namespace php tutorial
namespace perl tutorial
namespace haxe tutorial /**
* Thrift lets you do typedefs to get pretty names for your types. Standard
* C style here.
*/
typedef i32 MyInteger /**
* Thrift also lets you define constants for use across languages. Complex
* types and structs are specified using JSON notation.
*/
const i32 INT32CONSTANT = 9853
const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} /**
* You can define enums, which are just 32 bit integers. Values are optional
* and start at 1 if not supplied, C style again.
*/
enum Operation {
ADD = 1,
SUBTRACT = 2,
MULTIPLY = 3,
DIVIDE = 4
} /**
* Structs are the basic complex data structures. They are comprised of fields
* which each have an integer identifier, a type, a symbolic name, and an
* optional default value.
*
* Fields can be declared "optional", which ensures they will not be included
* in the serialized output if they aren't set. Note that this requires some
* manual management in some languages.
*/
struct Work {
1: i32 num1 = 0,
2: i32 num2,
3: Operation op,
4: optional string comment,
} /**
* Structs can also be exceptions, if they are nasty.
*/
exception InvalidOperation {
1: i32 whatOp,
2: string why
} /**
* Ahh, now onto the cool part, defining a service. Services just need a name
* and can optionally inherit from another service using the extends keyword.
*/
service Calculator extends shared.SharedService { /**
* A method definition looks like C code. It has a return type, arguments,
* and optionally a list of exceptions that it may throw. Note that argument
* lists and exception lists are specified using the exact same syntax as
* field lists in struct or exception definitions.
*/ void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), /**
* This method has a oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*/
oneway void zip() } /**
* That just about covers the basics. Take a look in the test/ folder for more
* detailed examples. After you run this file, your generated code shows up
* in folders with names gen-<language>. The generated code isn't too scary
* to look at. It even has pretty indentation.
*/

附上shared.thrift

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/ /**
* This Thrift file can be included by other Thrift files that want to share
* these definitions.
*/ namespace cpp shared
namespace d share // "shared" would collide with the eponymous D keyword.
namespace java shared
namespace perl shared
namespace php shared
namespace haxe shared struct SharedStruct {
1: i32 key
2: string value
} service SharedService {
SharedStruct getStruct(1: i32 key)
}


2、输入编译命令,将接口文件编译相应的语言java、nodejs。

>thrift -r --gen java tutorial.thrift

>thrift
-r --gen js:node tutorial.thrift

3、能够在当前文件夹下看到相应生成的文件夹gen-java、gen-nodejs;

    

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

4. 创建Java语言的server

1、在eclipse新建MavenProject名为thrift

2、创建CalculatorHandler.java和JavaServer.java文件。代码例如以下:

CalculatorHandler.java
package tutorial.impl;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
* file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/ import java.util.HashMap; import shared.SharedStruct;
// Generated code
import tutorial.Calculator;
import tutorial.InvalidOperation;
import tutorial.Work; public class CalculatorHandler implements Calculator.Iface { private HashMap<Integer, SharedStruct> log; public CalculatorHandler() {
log = new HashMap<Integer, SharedStruct>();
} public void ping() {
System.out.println("ping()");
} public int add(int n1, int n2) {
System.out.println("add(" + n1 + "," + n2 + ")");
return n1 + n2;
} public int calculate(int logid, Work work) throws InvalidOperation {
System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})");
int val = 0;
switch (work.op) {
case ADD:
val = work.num1 + work.num2;
break;
case SUBTRACT:
val = work.num1 - work.num2;
break;
case MULTIPLY:
val = work.num1 * work.num2;
break;
case DIVIDE:
if (work.num2 == 0) {
InvalidOperation io = new InvalidOperation();
io.whatOp = work.op.getValue();
io.why = "Cannot divide by 0";
throw io;
}
val = work.num1 / work.num2;
break;
default:
InvalidOperation io = new InvalidOperation();
io.whatOp = work.op.getValue();
io.why = "Unknown operation";
throw io;
} SharedStruct entry = new SharedStruct();
entry.key = logid;
entry.value = Integer.toString(val);
log.put(logid, entry); return val;
} public SharedStruct getStruct(int key) {
System.out.println("getStruct(" + key + ")");
return log.get(key);
} public void zip() {
System.out.println("zip()");
} }

3.JavaServer文件代码

package Server;

/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
* file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/ import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport; // Generated code
import tutorial.Calculator;
import tutorial.impl.CalculatorHandler; public class JavaServer { public static CalculatorHandler handler; public static Calculator.Processor processor; public static void main(String[] args) {
try {
handler = new CalculatorHandler();
processor = new Calculator.Processor(handler); Runnable simple = new Runnable() {
public void run() {
simple(processor);
}
};
Runnable secure = new Runnable() {
public void run() {
secure(processor);
}
}; new Thread(simple).start();
new Thread(secure).start();
} catch (Exception x) {
x.printStackTrace();
}
} public static void simple(Calculator.Processor processor) {
try {
TServerTransport serverTransport = new TServerSocket(9090);
TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); // Use this for a multithreaded server
// TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Starting the simple server...");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
} public static void secure(Calculator.Processor processor) {
try {
/*
* Use TSSLTransportParameters to setup the required SSL parameters. In this example we are setting the keystore
* and the keystore password. Other things like algorithms, cipher suites, client auth etc can be set.
*/
TSSLTransportParameters params = new TSSLTransportParameters();
// The Keystore contains the private key
params.setKeyStore("c:/.mykeystore", "jinking", null, null); /*
* Use any of the TSSLTransportFactory to get a server transport with the appropriate SSL configuration. You can
* use the default settings if properties are set in the command line. Ex: -Djavax.net.ssl.keyStore=.keystore and
* -Djavax.net.ssl.keyStorePassword=thrift
*
* Note: You need not explicitly call open(). The underlying server socket is bound on return from the factory
* class.
*/
TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(9091, 0, null, params);
TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); // Use this for a multi threaded server
// TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Starting the secure server...");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
}
}

4、配置须要的lib类库。编辑pom.xml文件,必备的类库有libthrift和slf4j-api

		<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.2</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.6.1</version>
</dependency>

5、用java文件夹下的keytool生成证书;

>keytool -certreq -keyalg RSA -alias myalias -file certreq.txt -keystore c:\.mykeystore

代码对应的改动成你生成的秘钥,红色字体标出;

params.setKeyStore("c:/.mykeystore", <span style="color:#ff0000;">"jinking"</span>, null, null);

6、执行javaServer.java文件,能够看到例如以下界面;

5. 创建nodejs版的client


1、首先就是要搭建nodejs环境和npm和express、安装相应模块。这个能够去网上搜索一下。不在此叙述。
可能会报错:Error: Cannot find module 'thrift'  和 Error: Cannot find module 'node-int64' 、Error: Cannot find module 'q'
则须要输入以下的文件夹安装相应的模块:
npm install -g node-int64  和  npm install -g thrift 、  npm install -g q
2、新建project文件夹client;
3、讲lib下的nodejs类库和gen-nodejs,复制到根文件夹下。路径例如以下:


4、创建NodeClient.js文件

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/ var thrift = require('./thrift');
var ThriftTransports = require('./thrift/transport');
var ThriftProtocols = require('./thrift/protocol');
var Calculator = require('./gen-nodejs/Calculator');
var ttypes = require('./gen-nodejs/tutorial_types'); transport = ThriftTransports.TBufferedTransport()
protocol = ThriftProtocols.TBinaryProtocol() var connection = thrift.createConnection("localhost", 9090, {
transport : transport,
protocol : protocol
}); connection.on('error', function(err) {
assert(false, err);
}); // Create a Calculator client with the connection
var client = thrift.createClient(Calculator, connection); client.ping(function(err, response) {
console.log('ping()');
}); client.add(1,1, function(err, response) {
console.log("1+1=" + response);
}); work = new ttypes.Work();
work.op = ttypes.Operation.DIVIDE;
work.num1 = 1;
work.num2 = 0; client.calculate(1, work, function(err, message) {
if (err) {
console.log("InvalidOperation " + err);
} else {
console.log('Whoa? You know how to divide by zero?');
}
}); work.op = ttypes.Operation.SUBTRACT;
work.num1 = 15;
work.num2 = 10; client.calculate(1, work, function(err, message) {
console.log('15-10=' + message); client.getStruct(1, function(err, message){
console.log('Check log: ' + message.value); //close the connection once we're done
connection.end();
});
});

5、输入:>node NodeClient.js

6、nodejsclient命令行窗体显示:

7、Javaserver端显示:

8、大功告成。

使用thrift框架实现了Java和nodejs之间的跨平台通信;

使用thrift实现了Javaserver和nodejsclient之间的跨平台通信的更多相关文章

  1. 跨平台通信中间件thrift学习【Java版本】(转)

    转自:http://neoremind.com/2012/03/%E8%B7%A8%E5%B9%B3%E5%8F%B0%E9%80%9A%E4%BF%A1%E4%B8%AD%E9%97%B4%E4%B ...

  2. 父窗口,子窗口之间的JS"通信"方法

    今天需要在iframe内做一个弹窗,但使用弹窗组件的为子窗口,所以弹窗只在子窗口中显示掩膜层和定位,这样不符合需求. 后来晓勇哥指点,了解到一个以前一直没关注到的东西,每个窗口的全局变量,其实都存在对 ...

  3. RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。

    RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大.最高效的方法之一.它为在分布式计算环境中运行的几乎所有应用程序提供基础.本文介绍 RPC 客户机和服务器之间基本的事件流 ...

  4. 安卓中不同APP之间的消息通信

    昨天在腾讯实习生招聘初试面试时面试官问道我关于两个APP之间相互通信的方式,当时自己回道到了contentProvider与BroadcastReceiver.但他接着问还有没有其它的方式,我跟他说可 ...

  5. Java与C之间的socket通信

    最近正在开发一个基于指纹的音乐检索应用,算法部分已经完成,所以尝试做一个Android App.Android与服务器通信通常采用HTTP通信方式和Socket通信方式.由于对web服务器编程了解较少 ...

  6. Handler主线程子线程之间的互相通信

    Handler主线程子线程之间的互相通信 package com.wyl.dansnote; import android.app.Activity; import android.os.Bundle ...

  7. 用vlan实现同一网段的的各部门之间有的可以通信有的不可以通信

    日前老师上课演示一个项目:实现公司同一网段的各个部门之间有的可以通信有的无法通信.我们用的是思科测试软件模拟操作,个人觉得很好用.       在刚开始做这个项目的时候我以为端口是对应的,如图,交换机 ...

  8. Android设备之间通过Wifi通信

    之前写过PC与Android之间通过WIFI通信(通过Socket,可以在博客里面搜索),PC作为主机,Android作为客户机,现在手头有一台仪器通过wifi传输数据,如果仪器作为主机发射WIFI热 ...

  9. 【单页应用之通信机制】view之间应该如何通信

    前言 在单页应用中,view与view之间的通信机制一直是一个重点,因为单页应用的所有操作以及状态管理全部发生在一个页面上 没有很好的组织的话很容易就乱了,就算表面上看起来没有问题,事实上会有各种隐忧 ...

随机推荐

  1. js实时监听input中值得变化

    <!DOCTYPE html> <html> <head> <title>zepto</title> <meta name=" ...

  2. [bzoj4514][SDOI2016]数字配对——二分图

    题目描述 传送门 题解: 这个题真的是巨坑,经过了6个WA,2个TLE,1个RE后才终于搞出来,中间都有点放弃希望了... 主要是一定要注意longlong! 下面开始说明题解. 朴素的想法是: 如果 ...

  3. 【查看linux配置】查看linux系统常用的命令,Linux查看系统配置常用命令

    一.linux CPU大小  cat /proc/cpuinfo |grep "model name" && cat /proc/cpuinfo |grep &qu ...

  4. VC2010编译libwebsockets

    1. 安装cmake: https://cmake.org/files/v3.6/cmake-3.6.0-win64-x64.msi 2. 下载libwebsocket源码: git clone ht ...

  5. JavaWeb响应下载(包含工具类)

    纸上得来终觉浅,绝知此事要躬行!今天博主分享是关于javaweb的响应(response)下载 以下是我的Demo: 页面我就粘主要部分的代码 <a href = "${pageCon ...

  6. 网站开发只需数小时?Meteor 说这才是未来

    原文: http://www.geekpark.net/topics/211573/ 那个想要挑战过去数十年沿用至今的网站开发模式的新势力来了. Meteor 是从 YC 孵化而出的现代网站开发平台, ...

  7. pymongo: MongoClient opened before fork错误排解

    使用pymongo配合flask和gunicorn使用的时候触发以下错误信息: [2017-09-19 15:20: ] [25780] [CRITICAL] WORKER TIMEOUT (pid: ...

  8. Codeforces538F A Heap of Heaps(函数式线段树)

    题意:给你一个数组a[n],对于数组每次建立一个完全k叉树,对于每个节点,如果父节点的值比这个节点的值大,那么就是一个违规点,统计出1~n-1完全叉树下的违规点的各自的个数. 一个直觉的思想就是暴力, ...

  9. web前端性能优化,提升静态文件的加载速度

    原文地址:传送门 WeTest 导读 此文总结了笔者在Web静态资源方面的一些优化经验. 如何优化 用户在访问网页时, 最直观的感受就是页面内容出来的速度,我们要做的优化工作, 也主要是为了这个目标. ...

  10. Codeforces 897 B.Chtholly's request-思维题(处理前一半)

      B. Chtholly's request   time limit per test 2 seconds memory limit per test 256 megabytes input st ...