前面介绍过 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(1: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
来源: https://www.cnblogs.com/zhangweizhong/p/11715313.html