gpt4 book ai didi

c# - SkipLastField 在结束组标记上调用。 GoogleProtobuf(C# 和 C++)

转载 作者:可可西里 更新时间:2023-11-01 02:51:09 30 4
gpt4 key购买 nike

我正在尝试使用 Google proto 在 C++ 中序列化一条消息,通过 TCP 套接字发送它,最后在 C# 客户端中接收并解析它。

我在 C# google proto 解析器上不断收到以下异常:

SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing

我在发送前和接收后都打印了序列化输入流,它在两端完美匹配。

C# 监听器/解串器

 namespace NetStreamHandler
{
public class Server
{
public static void ReceiveData()
{
var ipAddress = IPAddress.Parse("127.0.0.1");
var listener = new TcpListener(ipAddress, 20511);
listener.Start();
listener.BeginAcceptSocket(MessageReceived, listener);
}

private static void MessageReceived(IAsyncResult result)
{
var server = (TcpListener)result.AsyncState;
using (var client = server.EndAcceptTcpClient(result))
using (var stream = client.GetStream())
{
try
{
var cod = new CodedInputStream(stream);
var packet = Serialize.Parser.ParseFrom(cod);
Console.WriteLine($"Message: {packet.ToString()}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception Caught at: {ex.Message}\n");
}
}
}

}
}

C++ 发送/序列化

int bCount;
Serialized::Serialize pLoad;
pLoad.set_command("Test");
pLoad.set_id(10);
pLoad.set_num(3);
pLoad.set_packettype(1);
pLoad.set_ret("Test");

printf("Size after serializing: %d bytes\n", pLoad.ByteSize());
auto size = pLoad.ByteSize();
auto packet = new char[size];
ArrayOutputStream ArrayOut(packet, size);
auto coutput = new CodedOutputStream(&ArrayOut);
coutput->WriteVarint32(pLoad.ByteSize());
pLoad.SerializeToCodedStream(coutput);
auto sConnect = SetupSocket();
if (!sConnect) { printf("Socket failure\n"); goto DONE; }
std::cout << "Buffer:" << byte_2_str(packet, size) << std::endl;


bCount = send(sConnect, packet, size, 0);
if(bCount == SOCKET_ERROR)
{
fprintf(stderr, "Server: send() failed: error %d: %s\n", WSAGetLastError(), DecodeError(WSAGetLastError()));
goto DONE;
}
else if (bCount == -1) {
fprintf(stderr, "Error sending data %d\n", errno);
goto DONE;

}
else {
printf("Sent bytes %d\n", bCount);
}

DONE:
closesocket(sConnect);
printf("All done..\n");

最佳答案

您只为绑定(bind)到 CodedOutputStream 的 ArrayOut 中使用的缓冲区分配了负载大小字节。但是您尝试编写稍微多一些(有效负载大小 + (Varint32) 的大小。我猜您需要有足够大的缓冲区来存储具有消息长度的有效负载。

我使用的是 Poco 框架。下面是 C++ 示例代码:

void writeDelimitedTo(const google::protobuf::MessageLite& message, Poco::Net::StreamSocket& socket) {
int totalMsgSize = message.ByteSize()+4; // Variant32 length 1-4
char *buf = new char [totalMsgSize];
ArrayOutputStream aos(buf, totalMsgSize);
CodedOutputStream coded_output(&aos);
coded_output.WriteVarint32(message.ByteSize());
message.SerializeToCodedStream(&coded_output);
socket.sendBytes(buf, coded_output.ByteCount());
delete buf;
}

当然,C# 部分只是使用 System.Io.Stream 作为 clientStream。 ProtoMsgStructRequest 和 ProtoMsgStructResponse 是 ProtoBuf 消息:

using (var pbReader = new Google.Protobuf.CodedInputStream(clientStream, true))
{
var inRequest = new ProtoMsgStructRequest();
pbReader.ReadMessage(inRequest);
{
var outResponse = new ProtoMsgStructResponse();
using (var pbWriter = new Google.Protobuf.CodedOutputStream(clientStream, true))
{
pbWriter.WriteMessage(outResponse);
}
}
}

关于c# - SkipLastField 在结束组标记上调用。 GoogleProtobuf(C# 和 C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37396928/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com