前面介绍过 Thrift 安装和使用,介绍了Thrift服务的发布和客户端调用,可以查看我之前的文章:https://www.cnblogs.com/zhangweizhong/category/1006119.html

但是,之前介绍的都是单向的客户端发送消息,服务端接收消息。而客户端却得不到服务器的响应。

那如果我们要实现双向通信(即:客户端发送请求,服务端处理返回,服务端发送消息,客户端处理返回)的功能,该怎么实现呢?

其实在不涉及语言平台的制约,WebService或是webapi 就可以实现这种客户端发起请求,服务端的处理的单向流程。

然而,实际场景中,可能我们的某些业务需求,更需要服务端能够响应请求并处理数据。下面我通过一个demo案例,介绍下Thrift 是如何实现双向通信的。

一、安装Thrift

这里不再赘述,戳这里查看我上篇文章的介绍:https://www.cnblogs.com/zhangweizhong/category/1006119.html

二、编写Thrift IDL文件

编写thrift脚本,命名为student.thrift  如下:

service HelloWorldService{
void SayHello(:string msg);
}

生成service 的方法,之前的文章有介绍,这里就不介绍了。

三、编写服务端代码

创建HelloThrift.Server 服务端工程,添加HelloWorldBidirectionServer类,HelloWorldBidirectionServer 实现了Iface接口用于接收客户端消息,并有一个客户端传输层对象集合用于记录所有已连接的客户端。

 public class HelloWorldBidirectionServer : HelloWorldBidirectionService.Iface
{
public void Run(int port)
{
try
{
TServerTransport transport = new TServerSocket(port); TTransportFactory transportFac = new TTransportFactory(); TProtocolFactory inputProtocolFactory = new TBinaryProtocol.Factory();
TThreadPoolServer server = new TThreadPoolServer(getProcessorFactory(), transport, transportFac, inputProtocolFactory); server.Serve();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
} public static List<TTransport> TransportCollection = new List<TTransport>(); public void SayHello(string msg)
{
Console.WriteLine(string.Format("{0:yyyy/MM/dd hh:mm:ss} 服务端接收到消息: {1}", DateTime.Now, msg));
} public void SayToClient(string msg)
{
try
{
foreach (TTransport trans in TransportCollection)
{
TBinaryProtocol protocol = new TBinaryProtocol(trans);
HelloWorldBidirectionService.Client client = new HelloWorldBidirectionService.Client(protocol);
//Thread.Sleep(1000);
client.SayHello(msg);
//Console.WriteLine("发给了客户端哟");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
} public TProcessorFactory getProcessorFactory()
{
return new HelloWorldBidirectionProcessor();
}
} public class HelloWorldBidirectionProcessor : TProcessorFactory
{
public TProcessor GetProcessor(TTransport trans, TServer server = null)
{
if (trans.IsOpen)
{
HelloWorldBidirectionServer.TransportCollection.Add(trans);
Console.WriteLine("客户端连上。");
} HelloWorldBidirectionServer srv = new HelloWorldBidirectionServer();
return new global::HelloWorldBidirectionService.Processor(srv);
}
}

四、编写客户端代码

首先创建HelloThrift.Client客户端项目,添加接收服务端消息的类HelloWorldBidirectionClient,里面只有一个实现Iface接口的方法:

  public class HelloWorldBidirectionClient
{
static HelloWorldBidirectionService.Client client = null;
public void ConnectAndListern(int port, string ip = "127.0.0.1")
{
//Tsocket: TCP/IP Socket接口
TSocket tSocket = new TSocket(ip, port);
//消息结构协议
TProtocol protocol = new TBinaryProtocol(tSocket);
try
{
if (client == null)
{
client = new global::HelloWorldBidirectionService.Client(protocol);
tSocket.Open();//建立连接
StartListern(tSocket);//启动监听线程
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
} public void Say(string msg)
{
if (client != null)
client.SayHello(msg);
} void StartListern(TSocket tSocket)
{
Thread t = new Thread(new ParameterizedThreadStart(Run));
t.Start(tSocket);
} public void Run(object tSocket)
{
HelloWorldBidirectionService.Processor process = new HelloWorldBidirectionService.Processor(new HelloWorldBidirectionFace()); try
{
while (process.Process(new TBinaryProtocol((TSocket)tSocket), new TBinaryProtocol((TSocket)tSocket)))
{
Console.WriteLine("消息接收完成,等下一波,阻塞中......");
}
}
catch (Exception ex)
{
Console.WriteLine("连接断开..." + ex.Message);
}
} }
class HelloWorldBidirectionFace : HelloWorldBidirectionService.Iface
{
public void SayHello(string msg)
{
Console.WriteLine(string.Format("{0:yyyy/MM/dd hh:mm:ss} 收到服务端响应消息 {1}", DateTime.Now, msg)); }
}

实现客户端,ConnectAndListern方法可以与服务端建立连接,并开启客户端端口监听来自服务端的信息。Say方法可将消息发送至服务端。

五、测试

测试效果如下:

六、最后

  1. 关于使用Thrift 构建我们自己的rpc 的方法,这里基本讲完了。其他的方法本文就不再演示了,调用起来都是一样。

  2. 后续会简单讨论一下Thrift 框架的通信原理。

  3. 源代码下载,Weiz.Thrift.Shuangxiang.rar

Thrift总结(四)Thrift实现双向通信的更多相关文章

  1. Thrift笔记(四)--Thrift client源码分析

    thrift文件 namespace java com.gxf.demo namespace py tutorial typedef i32 int // We can use typedef to ...

  2. Thrift架构~动态Thrift插件的注入

    先说AOP 说到注入,大家就会想起来IoC和AOP,确实如些,这一讲中,我们通过unity来实现对thrift插件的动态注入,事实上,这个功能在以后的项目中经常要用到,比如,你将一些功能分发到指定服务 ...

  3. Thrift入门初探--thrift安装及java入门实例

    什么是thrift? 简单来说,是Facebook公布的一款开源跨语言的RPC框架. 那么问题来了. 什么是RPC框架? RPC全称为Remote Procedure Call,意为远程过程调用. 假 ...

  4. IDEA集成的 Thrift 插件进行 thrift 编译

    IDEA集成的 Thrift 插件进行 thrift 编译 注意 1.thrift文件要放在source目录,才有compile选项 2.generator list的output path不用加包名 ...

  5. 【thrift】thrift入门初探--thrift安装及java入门实例

    转载:https://www.cnblogs.com/fingerboy/p/6424248.html 公司的一些平台服务框架底层封装了thrift提供服务,最近项目不是很紧,于是研究了一下,刚刚入门 ...

  6. 【Thrift一】Thrift安装部署

    Thrift安装部署 Thrift安装部署 下载源码包 安装g++ 解压Thrift安装包 安装boost开发工具 测试(python版) 下载源码包 wget http://apache.fayea ...

  7. [development][thrift] RPC框架 thrift

    一: wiki:https://zh.wikipedia.org/wiki/Thrift 二: 来自IBM的介绍:https://www.ibm.com/developerworks/cn/java/ ...

  8. Thrift笔记(五)--Thrift server源码分析

    从(四)server代码跟进 public static void simple(MultiplicationService.Processor processor) { try { TServerT ...

  9. Thrift 个人实战--Thrift 网络服务模型

    前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...

随机推荐

  1. 流包装器实现WebShell免杀

    说明: 本文首发自 https://www.secpulse.com/archives/73391.html ,转载请注明出处. 前言 本文是看PHP使用流包装器实现WebShell有感,权当做个笔记 ...

  2. 网站是HTTP?10分钟变成HTTPS!域名免费添加配置SSL证书,变成https//环境

    对于小程序request请求需要https域名.navigator.geolocation定位也需要在https环境下才可以生效等问题: 前端开发越来越需要https环境来来测试一下API接口和各类问 ...

  3. 个人考场VIM配置

    前言 这个是我个人使用的Vim配置.双引号杠掉的部分是关于光标行列高亮(觉得难受而杠)和输入左括号同时打上右括号的(不习惯),如果要启用的话去掉引号即可. 将以下要启用的输入到$“./vimrc”$中 ...

  4. 【MongoDB详细使用教程】四、python操作MongoDB

    目录 1.安装pymongo 2.连接数据库 3.操作数据库 3.1.查 3.2.增 3.3.改 3.4.删 使用第三方库pymongo来实现python对MongoDB的操作 pymongo官方文档 ...

  5. Redis事务深入解析和使用

    作为关系型数据库中一项非常重要的基础功能--事务,在 Redis 中是如何处理并使用的? 1.前言 事务指的是提供一种将多个命令打包,一次性按顺序地执行的机制,并且保证服务器只有在执行完事务中的所有命 ...

  6. Lambda函数及其用法

    Lambda函数又称匿名函数,匿名函数就是没有名字的函数,函数没有名字也行? 当然可以啦.有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可. 先来看个简单lambda函 ...

  7. django-URL认识(一)

    URL由三部分组成:资源类型.存放资源的主机域名.资源文件名.也可认为由4部分组成:协议.主机.端口.路径 URL的一般语法格式为:(带方括号[]的为可选项): protocol :// hostna ...

  8. SpringCloud之Zuul高并发情况下接口限流(十二)

    高并发下接口限流技术gauva(谷歌的框架) MySql最大连接数3000: 原理:框架每秒向桶里放100个令牌,接口请求来了先去拿令牌,拿到令牌后才能继续向后走,否则不允许向后执行:当接口请求太频繁 ...

  9. else 的特殊用法和三目运算

    1,eval() 获取原始数据类型 例1: str = " a = eval(str) print(a,type(a)) a得到的结果是整型10,不是字符串10 例2: str1 = &qu ...

  10. 如何获取比 dism.log 更详细的日志

    正文 在工作中,曾经遇到过一个问题. 有一个 component,名字叫做 Oxford Adaptive Learning Dictionary,是一款牛津词典的应用.这个 component,需要 ...