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