FlatBuffers:用C ++编码与C#编码,在C#端到端示例中解码

时间:2016-06-08 17:24:02

标签: c# c++ flatbuffers

想象一下架构:

namespace MyEvents;  

table EventAddress  
{  
  id:uint;  
  timestamp:ulong;  
  adress:string;  
}  

table EventSignalStrength  
{  
  id:uint;  
  timestamp:ulong; 
  strength:float;   
}  

table EventStatus  
{  
  status:string;  
}  

union Events {EventAddress, EventSignalStrength, EventStatus}  

table EventHolder  
{  
  theEvent:Events;  
}  

root_type EventHolder;  

对于状态消息“EXIT”,在C ++中我编码并通过以下方式发送:

std::string message("EXIT");  
flatbuffers::FlatBufferBuilder builder;  
auto messageString= builder.CreateString(message);  // Message to send.  
auto statusEvent= MyEvents::CreateEventStatus(builder, messageString);  
auto eventHolder= MyEvents::CreateEventHolder(builder, MyEvents::Events_EventStatus, statusEvent.Union());  
builder.Finish(eventHolder);  

// Code to decode to check my work omitted, but the data decode properly in my real-world application.  

ret= sendto(m_udpSocket, reinterpret_cast<const char*>(builder.GetBufferPointer()), static_cast<int>(builder.GetSize()), 0, reinterpret_cast<SOCKADDR *>(&m_destination), sizeof(m_destination));  

对于相同的消息,“EXIT”,在C#中编码并通过以下方式发送:

string message= "EXIT";  
FlatBufferBuilder builder = new FlatBufferBuilder(1);  
StringOffset messageOffset = builder.CreateString(message);  
EventStatus.StartEventStatus(builder);  
EventStatus.AddStatus(builder, messageOffset);  
Offset<EventStatus> eventStatusOffset = EventStatus.EndEventStatus(builder);  

EventHolder.StartEventHolder(builder);  
EventHolder.AddTheEventType(builder, Events.EventStatus);  
EventHolder.AddTheEvent(builder, eventStatusOffset.Value);  
Offset<EventHolder> eventHolderOffset = EventHolder.EndEventHolder(builder);  

EventHolder.FinishEventHolderBuffer(builder, eventHolderOffset);  

// Test the encoding by decoding:  
EventHolder flatBuffer = EventHolder.GetRootAsEventHolder(builder.DataBuffer);  
Events flatBufferType = flatBuffer.TheEventType;  // Type looks good.  
EventStatus decodedEvent= new EventStatus();  
flatBuffer.GetDataObject<EventStatus>(decodedEvent);  // decodedEvent.Status looks good.  

// This code seems to send the correct data:  
Byte[] sendSized = builder.SizedByteArray();  
udpClient.Send(sendSized, sendSized.Length);  

// This code does not seem to send the correct data:  
//ByteBuffer sendByteBuffer = builder.DataBuffer;  
//udpClient.Send(sendByteBuffer.Data, sendByteBuffer.Data.Length);  

在我的客户端应用程序中,用C#编写,我解码为:

Byte[] receiveBytes = udpClient.Receive(ref m_remoteEndpoint);  
ByteBuffer flatBufferBytes= new ByteBuffer(receiveBytes);  
EventHolder flatBuffer = EventHolder.GetRootAsEventHolder(flatBufferBytes);  
Events flatBufferType= flatBuffer.DataObjectType;  
EventAddress eventAddress = null;  
EventSignalStrength eventSignalStrength = null;  
EventStatus eventStatus = null;  
switch (flatBufferType)  
{  
  case Events.EventAddress:  
  {  
    eventAddress = new EventAddress();  
    flatBuffer.GetDataObject<EventAddress>(eventAddress);  
    ProcessEventAddress(eventAddress);  
    break;  
  }  

  case Events.EventSignalStrength:  
  {  
    eventSignalStrength = new EventSignalStrength();  
    flatBuffer.GetDataObject<EventSignalStrength>(eventSignalStrength);  
    ProcessEventSignalStrength(eventSignalStrength);  
    break;  
  }  

  case Events.EventStatus:  
  {  
    eventStatus= new EventStatus();  
    flatBuffer.GetDataObject<EventStatus>(eventStatus);  
    Console.WriteLine("\nStatus Message: {0}", eventStatus.status);  
    break;  
  }  
}  
  • 当我从C ++应用程序收到EventStatus消息时,它们会正确解码。
  • 当我从C#发送应用程序收到EventStatus消息时,它们会正确解码。
  • 当我转储从应用程序发送的缓冲区时,它们是(十进制):

  • C ++ - 12 0 0 0 8 0 14 0 7 0 8 0 8 0 0 0 0 0 0 4 12 0 0 0 0 0 6 0 8 0 4 0 6 0 0 0 4 0 0 0 4 0 0 0 69 88 73 84 0 0 0 0

  • C# - 12 0 0 0 8 0 10 0 9 0 4 0 8 0 0 0 12 0 0 0 0 4 6 0 8 0 4 0 6 0 0 0 4 0 0 0 4 0 0 0 69 88 73 84 0 0 0 0

最初,来自C#发件人的邮件没有正确解码 - 现在是。我对发件人进行了更改,所以也许没有重建。

  • 我有点神秘的是收到的C ++缓冲区和C#缓冲区不同,但它们正确解码到相同的结果。
  • 我的真实架构要复杂得多 - 我是否遵循了在C#端进行解码的正确程序?
  • 我是否按照正确的程序将扁平缓冲区减少为Byte [],以便在C#中通过电线发送?它看起来像我,但它似乎没有工作一段时间....

任何意见都赞赏。

1 个答案:

答案 0 :(得分:0)

ByteBuffer包含缓冲区,但不一定在偏移0处,所以是的,将其转换为字节数组(或从其起始偏移量发送bytebuffer内容)是发送它的唯一正确方法。

语言之间的编码可能不同,因为实现可能会以不同的顺序序列化事物。这里,C ++实现决定在偏移之前写入union类型字段,这对于对齐来说恰好是低效的,因此它有点大。 C#恰恰相反。