C# 在C语言中读取Protobuf消息#
我有一个简单的信息:C# 在C语言中读取Protobuf消息#,c#,protobuf-net,C#,Protobuf Net,我有一个简单的信息: package test; message sendName { optional string username = 1; } awesome VS插件生成.cs文件: namespace test { [global::System.Serializable global::ProtoBuf.ProtoContract(Name=@"sendName")] public partial class sendName : global
package test;
message sendName {
optional string username = 1;
}
awesome VS插件生成.cs
文件:
namespace test {
[global::System.Serializable global::ProtoBuf.ProtoContract(Name=@"sendName")]
public partial class sendName : global::ProtoBuf.IExtensible {
public sendName() {}
private string _username = "";
[global::ProtoBuf.ProtoMember(1, IsRequired = false, Name=@"username", DataFormat = > global::ProtoBuf.DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string username
{
get { return _username; }
set { _username = value; }
}
private global::ProtoBuf.IExtension extensionObject;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{
return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
}
我通过使用从java端发送消息
objName.build().writeTo((FileOutputStream)socket.getOutputStream());
在我的C#应用程序中,它的作用类似于套接字侦听器,我有一个名为Listen的方法,用于侦听java客户端发送的消息:
public void Listen()
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(ipAddress, 4055);
TcpClient client = null;
listener.Start();
while (true)
{
Debug.WriteLine("Waiting for a Connection");
client = listener.AcceptTcpClient();
Stream stream = client.GetStream();
// sendName sendNameObj = Serializer.Deserialize<sendName>(stream);
}
}
这是我的java代码:
SendNameMessage.Builder sendNameMessageObj = null;
sendNameMessageObj = SendNameMessage.newBuilder();
sendNameMessageObj.setSendName("Protobuf-net");
SocketRequest.INSTANCE.openSocket();
sendNameMessageObj.build().writTo(SocketRequest.INSTANCE.getWriter());
序列化程序。反序列化(流)应该这么做,但我猜它会永远挂着?这里的原因是protobuf消息没有内置的终止符,因此默认情况下,它会一直读取到流的末尾,这在关闭套接字之前是不会发生的
为了避免这种情况,一个常见的技巧是在消息前面加上长度前缀,并限制自己的长度。在Java实现中可能有一种内置的方法来处理这个问题,或者您可以手动处理它。在C#端,protobuf net具有反序列化WithLengthPrefix
,它接受一个枚举来指定编码方式。为了简单起见,我建议使用一种基本的32位小尾端编码(它映射到PrefixStyle.Fixed32
)
重新编辑/注释:两者必须匹配。目前,您正在序列化而没有长度前缀,但反序列化需要长度前缀。JavaAPI是否公开了一种机制来在编写之前获取数据长度?如果没有,可能先写入一个临时缓冲区,查看您写入了多少,然后写入长度,最后写入数据
或;如果您只发送一条消息-只需关闭流并使用反序列化
(无长度前缀)。我有一个C#-to-C#多消息套接字示例可用,但我不能在java方面做太多评论…Marc,我一直收到一个“无效令牌:0”异常。你能告诉我这可能意味着什么吗?@sonu-这意味着它在一开始就找到了一个0,一堆数据,这永远都是无效的。当你看到这个时,你能添加一些关于数据流和代码的细节吗?对不起,我是stackoverflow的新手。我通过编辑帖子添加了代码。当我关闭java端的套接字时,我得到一个异常:“试图读取超过流的末尾”Marc,在java中有writedLimitedTo,这相当于反序列化WithLengthPrefix。我想那就行了。谢谢
SendNameMessage.Builder sendNameMessageObj = null;
sendNameMessageObj = SendNameMessage.newBuilder();
sendNameMessageObj.setSendName("Protobuf-net");
SocketRequest.INSTANCE.openSocket();
sendNameMessageObj.build().writTo(SocketRequest.INSTANCE.getWriter());