Thrift总结(四)Thrift实现双向通信
前面介绍过 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 的方法,之前的文章有介绍,这里就不介绍了。
三、编写服务端代码
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); } }
四、编写客户端代码
首先定义一个可以接收服务端消息的类,里面只有一个实现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. 源代码下载,HelloThrift.rar