2013-07-15 42 views
1

我試圖在C#和C++之間進行通信與不同數量的成功。無法返回使用Google協議緩衝區從C#到C + +和

我能夠使用回覆/請求在兩者之間發送消息,但我收到的雙打不正確。

爲了調試的目的和理解,我目前運行以下:

Clrzmq 3.0 RC1,谷歌ProtocolBuffer 2.5的Protobuf-CSHARP端口-2.4,ZeroMQ-3.2.3

.Proto

package InternalComm; 

message Point 
{ 
    optional double x = 1; 
    optional double y = 2; 
    optional string label = 3; 
} 

server.cpp(相關部分)

while (true) { 
    zmq::message_t request; 

    // Wait for next request from client 
    socket.recv (&request); 
    zmq::message_t reply (request.size()); 
    memcpy ((void*)reply.data(), request.data(), request.size()); 
    socket.send(reply); 
} 

客戶.cs(相關部分)

public static Point ProtobufPoint(Point point) 
    { 
     Point rtn = new Point(0,0); 
     using (var context = ZmqContext.Create()) 
     { 
      using (ZmqSocket requester = context.CreateSocket(SocketType.REQ)) 
      { 
       requester.Connect("tcp://localhost:5555"); 
       var p = InternalComm.Point.CreateBuilder().SetX(point.X).SetY(point.Y).Build().ToByteArray(); 

       requester.Send(p); 

       string reply = requester.Receive(Encoding.ASCII); 
       Console.WriteLine("Input: {0}", point); 

       byte[] bytes = System.Text.Encoding.ASCII.GetBytes(reply); 
       var message = InternalComm.Point.ParseFrom(bytes); 
       rtn.X = message.X; 
       rtn.Y = message.Y; 

       Console.WriteLine("Output: {0}", rtn); 
      } 
     } 
     return rtn; 
    } 

在C#端,Point是一個非常簡單的結構。只需x和y屬性。

下面是我從單元測試中得到的運行上述代碼的結果。

輸入(1.31616874365468,4.55516872325469)
輸出(0.000473917985115791,4.55516872323627)

輸入(274.120398471829,274.128936418736)
輸出(274.077917334613,274.128936049925)

輸入(150.123798461987, 2.345E-12)
輸出(145.976 459594794,1.11014954927532E-13)

輸入(150,0)
輸出(145.96875,0)

我想這個問題是我的protobuf的代碼不正確(懷疑這是一個錯誤在Skeet的一側)。我也在假設server.cpp對消息沒有任何作用,但按原樣返回。

想法?

+1

只是爲了確認:System.Text.Encoding.ASCII.GetBytes(reply);這絕對是一個巨大的問題。 Protobuf數據*不是ascii * –

回答

4

requestor.Receive(Encoding.ASCII)調用旨在接收一個字符串,而不是一個字節塊。您要求ZmqSocket實例將該消息作爲ASCII字符串返回,這很可能導致對內容的修改。如果你發送一個字節數組,接收一個字節數組。

嘗試這種情況:

int readSize; 
byte[] reply = requester.Receive(null, out readSize); 
var message = InternalComm.Point.ParseFrom(reply); 

readSize變量將包含在所接收的塊中的有效字節,這可從reply陣列的大小而變化的實際數量,因此可能需要把他們切片,所述陣列讓ProtoBuf變得可口。

+0

爲了澄清,當你說切片陣列時,你的意思是把信息分解成更小的電線?或者接收大消息更好地分解解析? – Elxx

+0

順便說一句,這解決了我的問題。從字節到字符串是問題。 – Elxx

+0

@Elxx我在昨天之前沒有使用過ProtocolBuffer,所以我不確定是否會很高興從緩衝區中只讀取它需要的字節並忽略緩衝區的其餘內容。仍然不確定這件事。如果在1024字節緩衝區中有18字節的數據與其他可能隨機的數據一起使用,那麼ProtocolBuffer是否按預期工作? – Corey

4

爲什麼ASCII - >字節 - >解析步驟?如果你解析字節,你應該讀取字節。如果你正在解析文本,你應該閱讀。

不必要的字符集轉換看起來很可能是錯誤的。

+0

其實,這是我發現將回復消息恢復爲可用形式的唯一途徑。你會推薦什麼作爲替代品?我同意它看起來很麻煩... – Elxx

+1

是的,將原始字節讀入C#字符串類型是數據損壞的祕訣。我不知道ZeroMQ,但必須有一個接收方法,它會給你原始字節。 –