簡體   English   中英

Google Protocol Buffer(Java to C ++)

[英]Google Protocol Buffer (Java to C++)

我試圖在Java和C ++之間建立TCP / IP套接字連接,在Windows上使用Java,在Raspberry Pi上使用C ++。 正在傳輸的消息是Google Protocol Buffer消息,其原型設置如下:

package package_name;

message Win2Pi{
    optional int32 num1= 1;
    optional int32 num2= 2;
    optional int32 num3= 3;
    optional int32 num4= 4;
    optional bool logic1= 5;
    optional bool logic2= 6;
    optional bool logic3= 7;
    optional bool logic4= 8;
    optional bool logic5= 9;
    optional int32 num5= 10;
    optional bool logic6= 11;
}

我有以下Java代碼(充當客戶端):

/* Java Code to Open Socket, Create Protobuf Message, and Send */
Socket clientSocket = new Socket(hostName, portNumber);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
WinToPi.Builder w2p = WinToPi.newBuilder();
w2p.setNum1(255);
w2p.setNum2(255);
w2p.setNum3(255);
w2p.setNum4(255);
w2p.setLogic1(true);
w2p.setLogic2(true);
w2p.setLogic3(true);
w2p.setLogic4(true);
w2p.setLogic5(false);
w2p.setNum5(7);
w2p.setLogic6(true);
w2p.build().writeTo(clientSocket.getOutputStream());

我有以下C ++代碼(作為服務器):

//Protobuf Setup Variables
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){ 
    std::cout << "Error Opening Socket!" << std::endl;
    exit(1); //error
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){ 
    std::cout << "Error on Binding!" << std::endl; ;
    exit(1); //error
}

listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
    std::cout << "ERROR on accept" << std::endl;
    exit(1);
}

/* Clear Buffer and Read Message from Client */
bzero(buffer,1024);
n = read(newsockfd,buffer,1023);

std::cout << "n: " << n << std::endl;

if (n < 0){ 
    std::cout << "Error Reading From Socket!" << std::endl;
}

/* Translate Shoreside to Pi Message */
std::string inputStr = std::string(buffer);
package_name::WinToPi w2p;
w2p.ParseFromString(inputStr);

使用靜態消息,我能夠接收適當數量的字節和值。 有了這個,我開始在Java端動態更改值。 但是,似乎在c ++方面,我將收到正確的字節數,但大多數變量(僅前幾個)的值不會改變。 當我在Java端檢查打包和傳輸的Google協議緩沖區消息時,似乎我發送了正確的值。 有沒有更好的方法來接收c ++中的Google Protocol Buffer消息?

你最大的問題似乎是:

std::string inputStr = std::string(buffer);

當你構造一個這樣的string - 從const char* - 它將尋找第一個NUL作為終結符。 你應該改用......

std::string inputStr = std::string(buffer, n);

...這將確保整個接收數據塊存儲在字符串中。

另一個問題:

  • 在套接字上read可能會返回通過多個調用發送的任何內容,因此您應該始終采用約定來確定何時停止讀取(例如,客戶端和發送方已知的固定字節數 - 可能來自結構大小,或者標記字符或序列,如換行符或NUL,或固定大小的長度前綴)

    • 這是緩沖流的一個自然結果:假設您的客戶端應用程序調用write / send三次,而操作系統太忙而無法將任何數據實際獲取到網絡數據包中:當它確實這樣做時,它可能適合第一個和第二個半秒“寫入”一個數據包,然后發送第二個的其余部分和第三個在另一個數據包中; 如果接收器希望每次read讀取多字節邏輯消息的開始,那么它們就會受到沖擊

至於更好的方法,對於一些小的隨意使用我發現boost::asio使得非常簡潔,清晰的代碼,並且很高興使用...許多文檔,示例,在線教程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM