http://www.cnblogs.com/xxxteam/archive/2013/04/15/3023159.html

利用thrift实现js与C#通讯的例子

关键字:thrift js javascript C# Csharp webservice

1.为什么要用thrift js C#?

1.1 首先,js 通过 thrift 访问C#,实际上是一种c/s模式。thrift是通信工具,js是客户端,C#是服务端。

1.2 使用js直接与thrift server通信。让web开发变得更简单。如果使用Web Service,你需要自己去实现C/S两端的序列化与反序列化操作,还需要自行处理异常,降低了开发效率。而thrift则会自动生成两端的操作类,你只需要处理方法内部的逻辑即可。

1.3 js直接与thrift server通信,可以提高性能,并且用C#开发server,开发效率也非常高。(那些web service弱爆了)

1.4 当然,我们不能只看到优点。用这种方法也有比较明显的缺点:如果使用web service,则网页与web service可以封装在一个工程里,部署到IIS上后,可以存在于一个网站内。而使用了thrift后,你还需要手动管理thrift程序。包括:

1.4.1 你需要拥有服务端的绝对控制权,比如,你可以直接登录服务器的操作系统上进行操作。因此,如果你只有一个网页空间,则不适合这种方法。当然,你也可以用web service里绑定thrift,但这样你又需要自己手动进行序列化与反序列操作,而且两次转换让性能更低,有违初衷

1.4.2 给thrift server程序增加自动启动,与监视程序,来完成thrift的崩溃后自动重启。

2.环境

Win7 - VS2012 - .net 4.0 C# 控制台工程(用来承载thrift)

Win7 - VS2012 - .net 4.0 C# Web工程(用来调试js,超方便)

3.步骤(以下步骤,对于小白来说,有些困难。QQ讨论群:23152359 )

3.1 去thrift官方下载thrift库,目前是0.9.0。

3.2 去thrift官方下载编译好的win下的thrift编译器,是一个exe文件。

3.3 写一个数据结构定义文件。我在这里只是用了服务,没有定义自定义数据结构。

data.txt:

1 service UserStorage
2 {
3 i32 Sum( 1: i32 arg_number1, 2: i32 arg_number2),
4 string GetString()
5 }

3.4 命令行下,用thrift编译器,对它进行编译:
        run.bat:

1 thrift-0.9.0.exe --gen csharp data.txt
2 thrift-0.9.0.exe --gen js data.txt
3 pause

3.5 建立一个名字为CSharpServer的C#控制台工程,.net 4.0的。

3.6 为这个工程,添加现有项目:thrift库目录\thrift-0.9.0\lib\csharp\src\Thrift.csproj,然后引用这个项目。

3.7 把thrift编译出来的UserStorage.cs(在gen-csharp目录里),拖动到解决方案管理器里的CSharpServer项目的根目录下,UserStorage.cs与Program.cs应该在同一级。

3.8 在CSharpServer项目里创建一个UserStorage的处理类UserStorageHandle.cs:(它应该与UserStorage.cs与Program.cs在同一级)

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace CSharpServer
7 {
8 public class UserStorageHandle : UserStorage.Iface
9 {
10
11 public UserStorageHandle()
12 {
13 ;
14 }
15
16 public int Sum(int arg_number1, int arg_number2)
17 {
18 int result = arg_number1 + arg_number2;
19 Console.WriteLine(DateTime.Now.ToString() + " 收到请求:Sum,参数:arg_number1 = " + arg_number1.ToString() + ",arg_number2 = " + arg_number2.ToString() + ",返回:result = " + result.ToString());
20 return result;
21 }
22
23 private static int Counter = 0;
24
25 public string GetString()
26 {
27 int currentCounter = System.Threading.Interlocked.Increment(ref UserStorageHandle.Counter);
28 Console.WriteLine(DateTime.Now.ToString() + " 收到请求:GetString,参数:没有,返回:result = \"thrift is OK : " + currentCounter.ToString() + "\"");
29 return "thrift is OK : " + currentCounter.ToString();
30 }
31
32 }
33 }

3.9 主程序Program.cs:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Thrift.Transport;
6 using Thrift.Protocol;
7 using Thrift.Server;
8 using System.Net;
9
10 namespace CSharpServer
11 {
12 class Program
13 {
14 private static HttpListener httpListener = null;
15 private static THttpHandler httpServer = null;
16
17 static void Main(string[] args)
18 {
19 string serviceUrl = "http://localhost:99/";
20 try
21 {
22 UserStorageHandle handle = new UserStorageHandle();
23 UserStorage.Processor processor = new UserStorage.Processor(handle);
24 TProtocolFactory protocolFactory = new TJSONProtocol.Factory();
25
26 Program.httpServer = new THttpHandler(processor, protocolFactory);
27
28 Program.httpListener = new HttpListener();
29 Program.httpListener.Prefixes.Add(serviceUrl);
30 Program.httpListener.Start();
31 IAsyncResult result = Program.httpListener.BeginGetContext(new AsyncCallback(WebRequestCallback), null);
32 Console.WriteLine("Thrift 服务成功启动,网址是 " + serviceUrl);
33 }
34 catch (System.Exception ex)
35 {
36 Console.WriteLine("发生错误:" + ex.Message);
37 Console.WriteLine("按回车键退出");
38 Console.ReadLine();
39 return;
40 }
41 Console.WriteLine("若需结束程序,请直接关闭窗口,或按回车。");
42 Console.ReadLine();
43 }
44
45 public static void WebRequestCallback(IAsyncResult result)
46 {
47 if (Program.httpListener == null)
48 {
49 Console.WriteLine("发生错误:HttpListener已经被关闭");
50 Console.WriteLine("按回车键退出");
51 Console.ReadLine();
52 return;
53 }
54
55 HttpListenerContext httpListenerContext = Program.httpListener.EndGetContext(result);
56
57 Program.httpListener.BeginGetContext(new AsyncCallback(WebRequestCallback), null);
58
59 Program.httpServer.ProcessRequest(httpListenerContext);
60 }
61
62 }
63 }

3.10 按F5,启动CSharpServer项目。

3.11 新开一个VS2012(内存不够的赶快去买),建立一个叫JsProject的C# .net 4.0 Web空工程。

3.12 去jquery官网下载jquery-1.9.1.js(mini版也行,随便)

3.13 把thrift编译的js文件data_types.js与UserStorage.js,thrift库的js库文件(thrift库目录\thrift-0.9.0\lib\js\thrift.js),以及刚下载的jq文件jquery-1.9.1.js,全部拖动到解决方案资源管理器的JsProject项目的根目录下:

data_types.js \ jquery-1.9.1.js \ thrift.js \ UserStorage.js 应该与Web.config在同一级。

3.14 在根目录下创建一个Test.html文件,Test.html 应该与Web.config在同一级:

Test.html:

 1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5 <title></title>
6 <script type="text/javascript" src="jquery-1.9.1.js"></script>
7 <script type="text/javascript" src="data_types.js"></script>
8 <script type="text/javascript" src="thrift.js"></script>
9 <script type="text/javascript" src="UserStorage.js"></script>
10
11 <script>
12 $(document).ready(function ()
13 {
14 var debugPosation = 0;
15 try
16 {
17 var transport = new Thrift.Transport("http://localhost:99");
18 var protocol = new Thrift.Protocol(transport);
19 var client = new UserStorageClient(protocol);
20
21 var result_GetString = client.GetString();
22 var result_Sum = client.Sum(255, 322);
23 }
24 catch (e)
25 {
26 alert("出错鸟:" + e.message);
27 }
28 });
29 </script>
30 </head>
31 <body>
32 </body>
33 </html>

3.15 给Test.html的 “ var debugPosation = 0; ” 这一行,下断点,然后F5,就可以看到效果了。

4.注意两个问题

4.1 由于web服务一般都是80端口,如果thrift端口与其不同,js在访问时会遇到跨域问题,js报错e.message = "拒绝访问"。但是,对于传说中的windows server,完全没有问题,因为,windows server支持.net的传说中的端口复用功能!因此,假设部署后,网站的iis的url为:http://www.baidu.com/XXX,则你最好给thrift server留一个二级域名,比如 http://www.baidu.com/ThriftService ,把这个留给thrift。最后,直接把thrift server的监听url,设置为这个 http://www.baidu.com/ThriftService 就OK了,不会有端口冲突问题,因为win Server + .net 支持tcp端口复用!!!! 如果你的网站的url还带有端口,比如 http://www.baidu.com:9999/XXX,或者IP形式:http://11.2.33.44:9999/XXX,则thriftservice也需要与它的端口相同,比如:http://www.baidu:9999/ThriftService 或 http://11.2.33.44:9999/ThriftService 。问,网站端口与thriftserver端口并不是80,而是9999,有没有问题?答:木有问题,端口复用功能依然会发挥作用。不过,端口复用技术,是通过让IIS和ThriftServer,把端口监听的工作,都交给System.exe去做,所有如果要做防火墙,要注意一下。防火墙参见这个帖子:http://www.cnblogs.com/xxxteam/archive/2013/04/22/3036082.html

4.2 网址的最后一个斜杠问题。js访问thrift service,网址最后一个字符,是不带斜杠的。比如http://www.baidu.com/XXX/,这个就是错误的,因为最后一个是斜杠。应该去掉最后一个斜杠,更正为: http://www.baidu.com/XXX  。而ThriftServer的监听网址,则最后一个斜杠是不能省去的。坑爹吧?当然了,这个问题可能会因为日后的补丁被修正,所以大家自己留意一下。

5.为什么不能使用js + thrift server方案?

看到这里傻眼了吧?上面白忙活大半天,但最后居然发现这个方案有问题?是的。

5.1 Thrift的定义,仅仅是一个通信工具,它不是能7*24运行的类似于iis这种服务提供程序。相对于wcf来说,thrift简单,所以高效。但正是因为它简单,所以它缺少很多在复杂网络环境下充当服务端的功能。在实际使用中,如果把它当成webService Server,则经常出问题。而且很多问题是try catch也抓不住,直接导致宿主程序崩溃的。所以,如果希望构建一个稳定的webService server,还是使用wcf之类的稳定方案为妙。

不过,这并不是说thrift就不行。thrift可以在系统内部来进行数据传输,但绝对不能放在外部。

5.2 js + thrift不支持异步调用!原因是,js只有以ajax方式进行远程服务调用才具有异步功能,但thrift封装的远程服务调用,不是ajax方式的。

其他更多问题详见 http://www.cnblogs.com/xxxteam/archive/2013/04/24/3040839.html

 
分类: C#

thrift js javascript C# Csharp webservice的更多相关文章

  1. Atitit.js javascript的rpc框架选型

    Atitit.js javascript的rpc框架选型 1. Dwr1 2. 使用AJAXRPC1 2.2. 数据类型映射表1 3. json-rpc轻量级远程调用协议介绍及使用2 3.1. 2.3 ...

  2. Immutable.js – JavaScript 不可变数据集合

    不可变数据是指一旦创建就不能被修改的数据,使得应用开发更简单,允许使用函数式编程技术,比如惰性评估.Immutable JS 提供一个惰性 Sequence,允许高效的队列方法链,类似 map 和 f ...

  3. Js(javaScript)的闭包原理

    问题?什么是js(javaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.  小编 ...

  4. 【转】Eclipse去除js(JavaScript)验证错误

    这篇文章主要是对Eclipse去除js(JavaScript)验证错误进行了介绍.在Eclipse中,js文件常常会报错.可以通过如下几个步骤解决 第一步:去除eclipse的JS验证:将window ...

  5. Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception process Vob7

    Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception processVob7 1. 1. javascript异常处理机制 ...

  6. Atitit.js javascript异常处理机制与java异常的转换.js exception process Voae

    Atitit.js javascript异常处理机制与java异常的转换.js exception processVoae 1. 1. javascript异常处理机制 1 2. 2. Web前后台异 ...

  7. atitit.js javascript 调用c# java php后台语言api html5交互的原理与总结p97

    atitit.js javascript 调用c# java php后台语言api html5交互的原理与总结p97 1. 实现html5化界面的要解决的策略1 1.1. Js交互1 1.2. 动态参 ...

  8. Atitit. servlet 与 IHttpHandler  ashx  listen 和HttpModule的区别与联系 原理理论 架构设计   实现机制    java php c#.net js javascript  c++ python

    Atitit. servlet 与 IHttpHandler  ashx  listen 和HttpModule的区别与联系 原理理论 架构设计   实现机制    java php c#.net j ...

  9. Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle

    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle 1. 主键1 2. uniq  index2 3.  ...

随机推荐

  1. Following unknown configure options were used:--enable-fpm

    跑cd   php-5.2.13安装时间 ./configure --prefix=/usr/local/php/ --with-config-file-path=/usr/local/php/etc ...

  2. 非阻塞IOserver型号

    让我们来考虑一个场景,你和百万玩家的魔兽世界的忠实粉丝.时间之旅打每到周末boss. 每当周末比赛server在亚历山大,因为至少在同一时间数十万用户在线. 假设我们的多-threaded果酱serv ...

  3. 使用Heroku,需要locale至zh_CN,代替zh-CN

    使用Heroku.需要locale至zh_CN,代替zh-CN 我认为这是由于在application.rb于,config.i18n.default_locale默认接受值这是Symbol, 而当我 ...

  4. WebKit介绍及总结(一)

    一 . WebKit 简单介绍 Webkit 是一个开放源码的浏览器引擎 (web browser engine) ,最初的代码来自 KDE 的 KHTML 和 KJS( 均开放源码 ) .苹果公司在 ...

  5. 源码编译安装 MySQL 5.5.x 实践(转)

    1.安装cmakeMySQL从5.5版本开始,通过./configure进行编译配置方式已经被取消,取而代之的是cmake工具.因此,我们首先要在系统中源码编译安装cmake工具. # wget ht ...

  6. DWR入门的例子(一个)

    DWR(Direct Web Remoting)是WEB远程调用框架.使用这种框架使AJAX发展至今已成为非常easy.使用DWR能client利用JavaScript直接调用服务端的Java方法并返 ...

  7. Oracle中的delete和truncate的关系

    转自:http://chenxy.blog.51cto.com/729966/168459 1.相同点       a.都可以删除数据,其中truncate用于全表清空数据,而delete可以选择的删 ...

  8. 十天学Linux内核之第五天---有关Linux文件系统实现的问题

    原文:十天学Linux内核之第五天---有关Linux文件系统实现的问题 有时间睡懒觉了,却还是五点多醒了,不过一直躺倒九点多才算起来,昨晚一直在弄飞凌的嵌入式开发板,有些问题没解决,自己电脑系统的问 ...

  9. ASP.NET AJAX简明教程

     当我们谈论Ajax时,首先想到的就是JavaScript下的Ajax,用来完成网页的交互,局部刷新工作,Microsoft的ASP.NET AJAX框架在Web的开发中承担着类似的角色,并简化了Ja ...

  10. 20天android学习

    20多天的实习(事实上,一个人学习的东西)要结束, 其余的都只有读研. 此20许多天,我学到了很多东西, 至android的发展也有一定的了解.之后写这篇文章主要是完成研究可以学得很快再次回升 1.安 ...