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中間語言的開發了,之所以說它是中間語言,是因為它不是最終我們要使用的,而需要將它進行編譯之后,才生成我們的目標語言,就像C語言,它在編譯時也是生成obj目標語言,然后再二次編譯最終生成exe文件,它們的道理是一樣的,

我們的thrift語言,通過thrift程序可以生成多種編程語言的源代碼。

編碼問題

使用VS建立一個thrift文件后,在進行編譯時出現了問題,最后找到答案,原來是編碼問題,最后使用記事本把編碼被為ANSI就可以正常編譯了。

Hello world程序代碼:

namespace csharp HelloThriftspace

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

service HelloThrift{
  void HelloWorld() throws (1:Xception ex)
}

編譯代碼:

thrift --gen csharp hellothrift.thrift 

結果:namespace表示文件夾的所在地,方法,結構,枚舉都是以文件形式存在的

 

生成的C#代碼:

Xception.cs

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

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在以后的產品中,對這塊解決的好一點,呵呵。

下一講我們將進行客戶端與服務器環境的搭建。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM