1
我想使用谷歌proto在C++中序列化消息,通過TCP套接字發送它,最後接收並解析它在C#客戶端。SkipLastField在終端組標籤上調用。 GoogleProtobuf(C#和C++)
我一直得到在C#谷歌原解析器以下例外:
SkipLastField稱爲上的端基標籤,表明相應的起始基團缺少
我打印的序列化輸入流在發送之前和接收之後都是完美匹配的。
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");
你收到的所有消息的您開始解析之前,服務器可以發送? 8000字節,但沒有保證TCP將在一個數據包中收到它,例如,它可能會被接收爲兩個4000字節的數據包。 'stream.Read(...)'將讀取4000字節並返回4000,然後再次調用4000,然後在最終調用時返回0以指示沒有數據要讀取。 –