Thrift架构~windows下安装和Hello World及编码引起的错误

最近开始正式接触Thrift架构,很牛B的技术,它被apache收纳了,属于开源中的一员,呵呵。

概念:

Thrift源于大名鼎鼎的facebook之手,在2007年facebook提交Apache基金会将Thrift作为一个开源项目,对于当时 的facebook来说创造thrift是为了解决facebook系统中各系统间大数据量的传 输通信以及系统之间语言环境不同需要跨平台的特性。所以thrift可以支持多种程序语言,例如:  C++, C#, Cocoa, Erlang, Haskell, Java, Ocami, Perl, PHP, Python, Ruby, Smalltalk. 在多种不同的语言之间通信thrift可以作为二进制的高性能的通讯中间件,支持数据(对象)序列化和多种类型的RPC服务。Thrift适用于程序对程 序静态的数据交换,需要先确定好他的数据结构,他是完全静态化的,当数据结构发生变化时,必须重新编辑IDL文件,代码生成,再编译载入的流程,跟其他 IDL工具相比较可以视为是Thrift的弱项,Thrift适用于搭建大型数据交换及存储的通用工具,对于大型系统中的内部数据传输相对于JSON和 xml无论在性能、传输大小上有明显的优势。

下面看一下windows下的安装与使用。

Thrift目前最高0.9.1,地址:http://archive.apache.org/dist/thrift/

注意,我们要把exe和tar文件都下载下来,exe用来编译你的thrift中间语言,而tar解压后,我们可以看到csharp,php,java,js等多种开发语言的实例代码,对我们很有帮助的,下载最新版

下载之后,我们把exe文件可以放在C盘,建个Thrift目录,把它放入,然后可以配置一下环境变量,如图:

Thrift架构~windows下安装和Hello World及编码引起的错误

然后,我们就可以进行thrift中间语言的开发了,之所以说它是中间语言,是因为它不是最终我们要使用的,而需要将它进行编译之后,才生成我们的目标语言,就像C语言,它在编译时也是生成obj目标语言,然后再二次编译最终生成exe文件,它们的道理是一样的,

我们的thrift语言,通过thrift程序可以生成多种编程语言的源代码。

编码问题

使用VS建立一个thrift文件后,在进行编译时出现了问题,最后找到答案,原来是编码问题,最后使用记事本把编码被为ANSI就可以正常编译了。

Thrift架构~windows下安装和Hello World及编码引起的错误

Hello world程序代码:

Thrift架构~windows下安装和Hello World及编码引起的错误
namespace csharp HelloThriftspace

exception Xception {
  1: i32 errorCode,
  2: string message
}

service HelloThrift{
  void HelloWorld() throws (1:Xception ex)
}
Thrift架构~windows下安装和Hello World及编码引起的错误

编译代码:

thrift --gen csharp hellothrift.thrift 

结果:namespace表示文件夹的所在地,方法,结构,枚举都是以文件形式存在的

Thrift架构~windows下安装和Hello World及编码引起的错误

 

生成的C#代码:

Xception.cs

Thrift架构~windows下安装和Hello World及编码引起的错误
namespace HelloThriftspace
{

  #if !SILVERLIGHT
  [Serializable]
  #endif
  public partial class Xception : TException, TBase
  {
    private int _errorCode;
    private string _message;

    public int ErrorCode
    {
      get
      {
        return _errorCode;
      }
      set
      {
        __isset.errorCode = true;
        this._errorCode = value;
      }
    }

    public string Message
    {
      get
      {
        return _message;
      }
      set
      {
        __isset.message = true;
        this._message = value;
      }
    }


    public Isset __isset;
    #if !SILVERLIGHT
    [Serializable]
    #endif
    public struct Isset {
      public bool errorCode;
      public bool message;
    }

    public Xception() {
    }

    public void Read (TProtocol iprot)
    {
      TField field;
      iprot.ReadStructBegin();
      while (true)
      {
        field = iprot.ReadFieldBegin();
        if (field.Type == TType.Stop) { 
          break;
        }
        switch (field.ID)
        {
          case 1:
            if (field.Type == TType.I32) {
              ErrorCode = iprot.ReadI32();
            } else { 
              TProtocolUtil.Skip(iprot, field.Type);
            }
            break;
          case 2:
            if (field.Type == TType.String) {
              Message = iprot.ReadString();
            } else { 
              TProtocolUtil.Skip(iprot, field.Type);
            }
            break;
          default: 
            TProtocolUtil.Skip(iprot, field.Type);
            break;
        }
        iprot.ReadFieldEnd();
      }
      iprot.ReadStructEnd();
    }

    public void Write(TProtocol oprot) {
      TStruct struc = new TStruct("Xception");
      oprot.WriteStructBegin(struc);
      TField field = new TField();
      if (__isset.errorCode) {
        field.Name = "errorCode";
        field.Type = TType.I32;
        field.ID = 1;
        oprot.WriteFieldBegin(field);
        oprot.WriteI32(ErrorCode);
        oprot.WriteFieldEnd();
      }
      if (Message != null && __isset.message) {
        field.Name = "message";
        field.Type = TType.String;
        field.ID = 2;
        oprot.WriteFieldBegin(field);
        oprot.WriteString(Message);
        oprot.WriteFieldEnd();
      }
      oprot.WriteFieldStop();
      oprot.WriteStructEnd();
    }

    public override string ToString() {
      StringBuilder sb = new StringBuilder("Xception(");
      sb.Append("ErrorCode: ");
      sb.Append(ErrorCode);
      sb.Append(",Message: ");
      sb.Append(Message);
      sb.Append(")");
      return sb.ToString();
    }

  }

}
View Code

HelloThrift.cs

Thrift架构~windows下安装和Hello World及编码引起的错误
namespace HelloThriftspace
{
  public partial class HelloThrift {
    public interface Iface {
      void HelloWorld();
      #if SILVERLIGHT
      IAsyncResult Begin_HelloWorld(AsyncCallback callback, object state);
      void End_HelloWorld(IAsyncResult asyncResult);
      #endif
    }

    public class Client : IDisposable, Iface {
      public Client(TProtocol prot) : this(prot, prot)
      {
      }

      public Client(TProtocol iprot, TProtocol oprot)
      {
        iprot_ = iprot;
        oprot_ = oprot;
      }

      protected TProtocol iprot_;
      protected TProtocol oprot_;
      protected int seqid_;

      public TProtocol InputProtocol
      {
        get { return iprot_; }
      }
      public TProtocol OutputProtocol
      {
        get { return oprot_; }
      }


      #region " IDisposable Support "
      private bool _IsDisposed;

      // IDisposable
      public void Dispose()
      {
        Dispose(true);
      }
      

      protected virtual void Dispose(bool disposing)
      {
        if (!_IsDisposed)
        {
          if (disposing)
          {
            if (iprot_ != null)
            {
              ((IDisposable)iprot_).Dispose();
            }
            if (oprot_ != null)
            {
              ((IDisposable)oprot_).Dispose();
            }
          }
        }
        _IsDisposed = true;
      }
      #endregion


      
      #if SILVERLIGHT
      public IAsyncResult Begin_HelloWorld(AsyncCallback callback, object state)
      {
        return send_HelloWorld(callback, state);
      }

      public void End_HelloWorld(IAsyncResult asyncResult)
      {
        oprot_.Transport.EndFlush(asyncResult);
        recv_HelloWorld();
      }

      #endif

      public void HelloWorld()
      {
        #if !SILVERLIGHT
        send_HelloWorld();
        recv_HelloWorld();

        #else
        var asyncResult = Begin_HelloWorld(null, null);
        End_HelloWorld(asyncResult);

        #endif
      }
      #if SILVERLIGHT
      public IAsyncResult send_HelloWorld(AsyncCallback callback, object state)
      #else
      public void send_HelloWorld()
      #endif
      {
        oprot_.WriteMessageBegin(new TMessage("HelloWorld", TMessageType.Call, seqid_));
        HelloWorld_args args = new HelloWorld_args();
        args.Write(oprot_);
        oprot_.WriteMessageEnd();
        #if SILVERLIGHT
        return oprot_.Transport.BeginFlush(callback, state);
        #else
        oprot_.Transport.Flush();
        #endif
      }

      public void recv_HelloWorld()
      {
        TMessage msg = iprot_.ReadMessageBegin();
        if (msg.Type == TMessageType.Exception) {
          TApplicationException x = TApplicationException.Read(iprot_);
          iprot_.ReadMessageEnd();
          throw x;
        }
        HelloWorld_result result = new HelloWorld_result();
        result.Read(iprot_);
        iprot_.ReadMessageEnd();
        if (result.__isset.ex) {
          throw result.Ex;
        }
        return;
      }

    }
    public class Processor : TProcessor {
      public Processor(Iface iface)
      {
        iface_ = iface;
        processMap_["HelloWorld"] = HelloWorld_Process;
      }

      protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);
      private Iface iface_;
      protected Dictionary<string, ProcessFunction> processMap_ = new Dictionary<string, ProcessFunction>();

      public bool Process(TProtocol iprot, TProtocol oprot)
      {
        try
        {
          TMessage msg = iprot.ReadMessageBegin();
          ProcessFunction fn;
          processMap_.TryGetValue(msg.Name, out fn);
          if (fn == null) {
            TProtocolUtil.Skip(iprot, TType.Struct);
            iprot.ReadMessageEnd();
            TApplicationException x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, "Invalid method name: ‘" + msg.Name + "");
            oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));
            x.Write(oprot);
            oprot.WriteMessageEnd();
            oprot.Transport.Flush();
            return true;
          }
          fn(msg.SeqID, iprot, oprot);
        }
        catch (IOException)
        {
          return false;
        }
        return true;
      }

      public void HelloWorld_Process(int seqid, TProtocol iprot, TProtocol oprot)
      {
        HelloWorld_args args = new HelloWorld_args();
        args.Read(iprot);
        iprot.ReadMessageEnd();
        HelloWorld_result result = new HelloWorld_result();
        try {
          iface_.HelloWorld();
        } catch (Xception ex) {
          result.Ex = ex;
        }
        oprot.WriteMessageBegin(new TMessage("HelloWorld", TMessageType.Reply, seqid)); 
        result.Write(oprot);
        oprot.WriteMessageEnd();
        oprot.Transport.Flush();
      }

    }


    #if !SILVERLIGHT
    [Serializable]
    #endif
    public partial class HelloWorld_args : TBase
    {

      public HelloWorld_args() {
      }

      public void Read (TProtocol iprot)
      {
        TField field;
        iprot.ReadStructBegin();
        while (true)
        {
          field = iprot.ReadFieldBegin();
          if (field.Type == TType.Stop) { 
            break;
          }
          switch (field.ID)
          {
            default: 
              TProtocolUtil.Skip(iprot, field.Type);
              break;
          }
          iprot.ReadFieldEnd();
        }
        iprot.ReadStructEnd();
      }

      public void Write(TProtocol oprot) {
        TStruct struc = new TStruct("HelloWorld_args");
        oprot.WriteStructBegin(struc);
        oprot.WriteFieldStop();
        oprot.WriteStructEnd();
      }

      public override string ToString() {
        StringBuilder sb = new StringBuilder("HelloWorld_args(");
        sb.Append(")");
        return sb.ToString();
      }

    }


    #if !SILVERLIGHT
    [Serializable]
    #endif
    public partial class HelloWorld_result : TBase
    {
      private Xception _ex;

      public Xception Ex
      {
        get
        {
          return _ex;
        }
        set
        {
          __isset.ex = true;
          this._ex = value;
        }
      }


      public Isset __isset;
      #if !SILVERLIGHT
      [Serializable]
      #endif
      public struct Isset {
        public bool ex;
      }

      public HelloWorld_result() {
      }

      public void Read (TProtocol iprot)
      {
        TField field;
        iprot.ReadStructBegin();
        while (true)
        {
          field = iprot.ReadFieldBegin();
          if (field.Type == TType.Stop) { 
            break;
          }
          switch (field.ID)
          {
            case 1:
              if (field.Type == TType.Struct) {
                Ex = new Xception();
                Ex.Read(iprot);
              } else { 
                TProtocolUtil.Skip(iprot, field.Type);
              }
              break;
            default: 
              TProtocolUtil.Skip(iprot, field.Type);
              break;
          }
          iprot.ReadFieldEnd();
        }
        iprot.ReadStructEnd();
      }

      public void Write(TProtocol oprot) {
        TStruct struc = new TStruct("HelloWorld_result");
        oprot.WriteStructBegin(struc);
        TField field = new TField();

        if (this.__isset.ex) {
          if (Ex != null) {
            field.Name = "Ex";
            field.Type = TType.Struct;
            field.ID = 1;
            oprot.WriteFieldBegin(field);
            Ex.Write(oprot);
            oprot.WriteFieldEnd();
          }
        }
        oprot.WriteFieldStop();
        oprot.WriteStructEnd();
      }

      public override string ToString() {
        StringBuilder sb = new StringBuilder("HelloWorld_result(");
        sb.Append("Ex: ");
        sb.Append(Ex== null ? "<null>" : Ex.ToString());
        sb.Append(")");
        return sb.ToString();
      }

    }

  }
}
View Code

感觉生成的代码还是比较麻烦的,希望thrift在以后的产品中,对这块解决的好一点,呵呵。

下一讲我们将进行客户端与服务器环境的搭建。

Thrift架构~windows下安装和Hello World及编码引起的错误

上一篇:ASP.NET MVC 5 - 添加一个模型


下一篇:小程序中自定义代用输入框的模态框弹窗