2

我已經在C#編寫此protobuf的消息序列化和發送協議緩衝器消息

  • C#客戶端:

    public AddressBook InitializeAdressBook() { 
    
         Person newContact = new Person(); 
         AddressBook addressBookBuilder = new AddressBook(); 
         Person john = new Person(); 
         john.id=1234; 
         john.name="John Doe"; 
         john.email="[email protected]"; 
         Person.PhoneNumber nr = new Person.PhoneNumber(); 
         nr.number="5554321"; 
         john.phone.Add(nr); 
         addressBookBuilder.person.Add(john); 
         TextBox.Text += ("Client: Initialisiert? " + addressBookBuilder.ToString()) + "\t" + "\n"; 
         TextBox.Text += " Erster Person " + addressBookBuilder.person.First().name + "\t" + "\n"; 
    
         return addressBookBuilder; 
        } 
    

問題

我想發送protobuf消息AC#客戶端這個Java服務器...

  • Java服務器

    public ControllerThread(Socket s){ 
    this.s = s; 
    try { 
         AddressBook adb = AddressBook.parseFrom(s.getInputStream()); 
         System.out.println("Server: Addressbook:" + adb.getPersonCount()); 
    
        } catch (IOException e) { 
         System.out.println("Server: BufferedReader oder PrintWriter von ThermoClient konnte nicht erstellt werden"); 
         e.printStackTrace(); } 
        } 
    

    }

問:

我應該序列化此消息一個字節數組,以便我可以發送它的Java服務器... 不幸的是,方法ProtoBuf.Serializer.Serialize不返回一個字節數組。 那麼我怎麼能序列化它作爲一個字節數組,並將其發送到我的Java服務器?任何幫助讚賞謝謝!

+0

它取決於很多什麼通信協議並您的服務器提供 – Vlad

+0

所以,「連載」使用生成器的八位字節流,然後使用適當的庫Java來「反序列化」它。如果您從'.protobuf'文件創建Proto對象,則應該爲這兩種語言自動綁定。請記住,* ProtocolBuffers是二進制*。 – 2012-10-31 19:00:22

+0

服務器使用太protobuf – Kaiser4you

回答

4

protobuf-net(又名ProtoBuf.Serializer.Serialize)寫入。如果您的套接字爲NetworkStream,則可以直接寫入該套接字。如果你真的想要一個byte[],然後用MemoryStream

byte[] data; 
using(var ms = new MemoryStream()) { 
    Serializer.Serialize(ms, obj); 
    data = ms.ToArray(); 
} 
+0

謝謝!它是否會使服務器直接寫入流或發送字節數組有所不同? – Kaiser4you

+1

@ Kaiser4you,它依賴於消息的大小和消息的結構;在某些情況下(一個巨大的,僅僅轉發的消息),直接寫入流可能會更有效,以防止將其緩存到內存中,但在大多數常規用法中,您不會注意到很多差異。一個輕微的優化是使用'.GetBuffer()'而不是'.ToArray()',***但是***你必須**只寫** ms.Length'字節 - 的後備緩衝區一個'MemoryStream'是*超大*,並且包含垃圾/零,你*不能*寫入流。 –

+0

你有沒有任何機會直接寫入網絡流而不是內存流的代碼示例:)? – Sir

1

首先,您最好仔細檢查Java服務器的協議。如here所述protobuf不是自行劃分的。這意味着如果你有一個TCP連接並且發送了多個protobuf消息,那麼必須有一些其他的底層協議來處理成幀 - 確定一個消息結束和另一個開始的地方。

讓我們暫時忽略這個問題。序列化消息的實際代碼取決於您正在使用的C#/ protobuf庫。如果您正在使用喬恩斯基特的protobuf-csharp-port你可能會序列化這樣說:

AddressBook book = InitializeAddressBook(); 
byte[] bookBytes = book.ToByteArray(); 

bookBytes是地址簿,序列化到一個字節數組。然後使用任何您想要的套接字庫(例如TcpClient)將數據(bookBytes)發送到Java服務器。

我不相信這會起作用,因爲我認爲有關於您未告訴我們的Java服務器的詳細信息。

+0

我正在使用Marc Gravell的c#protobuf庫v2。也許因此我沒有方法book.ToByteArray(); Jon Skeets的實施更好嗎? 我想發送多個郵件到一個單一的流。 Java Sever使用以下套接字通信 – Kaiser4you

+0

public ControllerThread(Socket s){this; s; s; try { br = new BufferedReader(new InputStreamReader(s.getInputStream())); (IOException e){「Server:BufferedReader oder PrintWriter von ThermoClient konnte nicht erstellt werden」);}};}};}}; \t \t \t e.printStackTrace(); \t \t} \t} – Kaiser4you

+0

我正在使用Marc Gravell的c#protobuf庫v2(http://code.google.com/p/protobuf-net/)。也許因此我沒有方法book.ToByteArray(); Jon Skeets的實施更好嗎? – Kaiser4you