C#客户端和Java服务端Thrift通信

最近帮老师做项目,需要用C#作为客户端做传输大量数据给Java服务端,之前的代码是用原生Socket写的,Java端这边非常的冗余复杂,难以维护,因此想到使用rpc框架来实现,方便后续的扩展和维护。

查阅资料发现thrift框架提供了完整的序列化和传输。(考虑效率也可使用protobuf+grpc,文档更加丰富)

关于rpc的框架对比,见:https://tech.meituan.com/2015/02/26/serialization-vs-deserialization.html

https://blog.csdn.net/z69183787/article/details/52605653

thrift这个框架的文档太少了,想真的把框架落地使用太难了5555......网上资料参差不齐,但是整了很久也算搞出来了,因此记录一下整个过程和走过的坑。

我是在本地测试的C#和Java都在windows端,首先安装thrift。

各个版本的链接如下:http://archive.apache.org/dist/thrift/

dll

我这里下的是  thrift-0.10.0.tar.gz 版本,环境是VS2019以及.NET 4.5,打开工程:thrift-0.10.0\lib\csharp\src\Thrift.sln,重新生成,编译,即可生成Thrift.dll(位置在thrift-0.10.0\lib\csharp\src\bin\Debug\Thrift.dll),后面编写代码的时候需要引用这个dll。

dat.drift

新建dat.drift文件,使用IDL对接口进行描述,用于生成.cs和.java代码。这一步需要用到Linux系统环境(没有的话建议使用虚拟机装Linux环境),因为我在Win10环境下按照网上的方法是无法生成对应的代码文件的。

IDL描述语言可以参考:https://diwakergupta.github.io/thrift-missing-guide/#_types

https://gitbox.apache.org/repos/asf?p=thrift.git;a=blob;hb=HEAD;f=tutorial/tutorial.thrift

示例如下:

定义了一个结构体和一个service方法

struct Dat{
	1: bool isColDat
	2: list<byte> data
}

service SendDatService{
	oneway void send(1:Dat dat)
}

这里的oneway表示方法调用不需要返回值,这样的话提高了调用的效率,但是可靠性不能保证。

在linux环境下安装thrift,参考:https://blog.csdn.net/huangbaokang/article/details/80065606

安装成功后,使用thrift生成.cs文件,在Linux命令行中执行

thrift -r --gen csharp dat.thrift

当前目录下会生成gen-csharp目录,里面是.cs文件,在编码时需要拷贝到C#工程目录下。

在Linux命令行中执行

thrift -r --gen java dat.thrift

当前目录下会生成gen-java目录,里面是.java文件,在编码时需要拷贝到Java工程目录下。

客户端代码

C#新建项目,引入前面生成Thrift.dll,复制前面生成的.cs文件到项目中,主程序示例代码如下。

using System;
using System.Collections.Generic;
using Thrift.Protocol;
using Thrift.Transport;

namespace IBAClientLT
{
    static class Program
    {
        public const string SERVERIP = "localhost";
        public static int SERVERPORT = 9000;
        public static int TIMEOUT = 5000;

        [STAThread]
        static void Main()
        {
            TTransport transport = null;
            try
            {
                //transport = new TSocket(SERVERIP, SERVERPORT, TIMEOUT);
                transport = new TFramedTransport(new TSocket(SERVERIP, SERVERPORT, TIMEOUT));
                //协议要和服务端一致
                TProtocol protocol = new TCompactProtocol(transport);
                SendDatService.Client client = new SendDatService.Client(protocol);
                transport.Open();
                
                Dat d = new Dat();
                d.IsColDat = false;
                List<sbyte> bt = new List<sbyte>();
                bt.Add(1);
                bt.Add(2);
                bt.Add(3);
                d.Data = bt;
                client.send(d);//远程调用
                client.Dispose();
                Console.ReadKey();//保持命令行窗口不关闭
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace);
            }
            finally
            {
                if (null != transport)
                {
                    //close
                    transport.Close();
                }
            }

        }
    }
}

服务端代码

Java新建Maven项目,pom.xml文件添加依赖

<!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
         <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.10.0</version>
            <!--<type>pom</type>-->
        </dependency>

继承我们定义的service接口,并且实现接口中的方法,这里我们打印出来内容。

package thrift;

import org.apache.thrift.TException;

public class SendDatServiceImpl implements SendDatService.Iface {
    @Override
    public void send(Dat dat) throws TException {
        System.out.println("iscolDat: "+dat.isColDat);
        System.out.println("data: "+dat.data);
    }
}

服务端主程序。

package thrift;

import org.apache.thrift.TNonblockingMultiFetchClient;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;

public class ThriftServer {
    public static void main(String[] args) throws TTransportException {
        TNonblockingServerSocket socket =new TNonblockingServerSocket(9000);
        THsHaServer.Args arg  =new THsHaServer.Args(socket).minWorkerThreads(1).maxWorkerThreads(4);
        SendDatService.Processor<SendDatServiceImpl> processor=
                new SendDatService.Processor<SendDatServiceImpl>(new SendDatServiceImpl());

        arg.protocolFactory(new TCompactProtocol.Factory());
        arg.transportFactory(new TFramedTransport.Factory());
        arg.processorFactory(new TProcessorFactory(processor));

        TServer server =new THsHaServer(arg);
        System.out.println("server start");
        server.serve();
    }
}

猜你喜欢

转载自blog.csdn.net/qinian_ztc/article/details/109432787