Sending protobuf from C ++ to Java

I am trying to send protobuf from a C ++ application to a Java application over a socket. I am using a simple socket in mu c ++ program to send protobuf. I passed it in a char buffer before sending it over the network. In my Java program (server), I am using ServerSocket to receive data.

I'm having a problem de-serializing protobuf on the Java side. It keeps giving me errors:

  • When parsing a log message, the logon ends unexpectedly in the middle of the field. This can mean either the input has been truncated or the inline message has skewed its own length.
  • CodedInputStream encountered an invalid varint.

What am I doing wrong? My code is below.

The protobuf example is taken from google tutorial - AddressBook.proto tutorial

C ++ code:

#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <fstream>
#include <string>   
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include<conio.h>
#include "addressbook.pb.h"

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

using namespace std;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
    cout << "Enter person ID number: ";
    int id;
    cin >> id;
    person->set_id(id);
    cin.ignore(256, '\n');

    cout << "Enter name: ";
    getline(cin, *person->mutable_name());

    cout << "Enter email address (blank for none): ";
    string email;
    getline(cin, email);
    if (!email.empty()) {
        person->set_email(email);
    }

    while (true) {
        cout << "Enter a phone number (or leave blank to finish): ";
        string number;
        getline(cin, number);
        if (number.empty()) {
            break;
        }

        tutorial::Person::PhoneNumber* phone_number = person->add_phone();
        phone_number->set_number(number);

        cout << "Is this a mobile, home, or work phone? ";
        string type;
        getline(cin, type);
        if (type == "mobile") {
            phone_number->set_type(tutorial::Person::MOBILE);
        }
        else if (type == "home") {
            phone_number->set_type(tutorial::Person::HOME);
        }
        else if (type == "work") {
            phone_number->set_type(tutorial::Person::WORK);
        }
        else {
            cout << "Unknown phone type.  Using default." << endl;
        }
    }
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
int main(int argc, char* argv[]) {
    // Verify that the version of the library that we linked against is
    // compatible with the version of the headers we compiled against.
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    tutorial::AddressBook address_book;


    // Add an address.
    PromptForAddress(address_book.add_person());

    {
        int size = address_book.ByteSize();
        char * buffer = new char[size];
        address_book.SerializeToArray(buffer, size);

        WSADATA wsaData;
        SOCKET ConnectSocket = INVALID_SOCKET;
        struct addrinfo *result = NULL,
                *ptr = NULL,
                hints;
        int iResult;

        // Initialize Winsock
        iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

        ZeroMemory(&hints, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;

        // Resolve the server address and port
        iResult = getaddrinfo("localhost", "5000", &hints, &result);
        if (iResult != 0) {
            printf("getaddrinfo failed with error: %d\n", iResult);
            WSACleanup();
            return 1;
        }

        // Attempt to connect to an address until one succeeds
        for (ptr = result; ptr != NULL; ptr = ptr->ai_next) 
        {

            // Create a SOCKET for connecting to server
            ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
                    ptr->ai_protocol);

            // Connect to server.
            iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
            if (iResult == SOCKET_ERROR) {
                closesocket(ConnectSocket);
                ConnectSocket = INVALID_SOCKET;
                continue;
            }
            freeaddrinfo(result);

            // Send an initial buffer
            iResult = send(ConnectSocket, buffer, (int)strlen(buffer), 0);
            if (iResult == SOCKET_ERROR) {
                printf("send failed with error: %d\n", WSAGetLastError());
                closesocket(ConnectSocket);
                WSACleanup();
                return 1;
            }
            printf("Bytes Sent: %ld\n", iResult);

            _getch();
            // Optional:  Delete all global objects allocated by libprotobuf.
            google::protobuf::ShutdownProtobufLibrary();

            return 0;
        }
    }
}

      

Java program:

package networkmonitor;

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.Parser;
import java.io.IOException;
import java.io.InputStream;
import static java.lang.System.in;
import java.net.ServerSocket;
import java.net.Socket;

class NetworkMonitor {
    // Iterates though all people in the AddressBook and prints info about them.
    static void Print(AddressBook addressBook) {
        for (Person person: addressBook.getPersonList()) {
            System.out.println("Person ID: " + person.getId());
            System.out.println("  Name: " + person.getName());
            if (person.hasEmail()) {
                System.out.println("  E-mail address: " + person.getEmail());
            }

            for (Person.PhoneNumber phoneNumber : person.getPhoneList()) {
                switch (phoneNumber.getType()) {
                case MOBILE:
                    System.out.print("  Mobile phone #: ");
                    break;
                case HOME:
                    System.out.print("  Home phone #: ");
                    break;
                case WORK:
                    System.out.print("  Work phone #: ");
                    break;
                }
                System.out.println(phoneNumber.getNumber());
            }
        }
    }

    // Main function:  Reads the entire address book from a file and prints all
    //   the information inside.
    public static void main(String[] args) throws Exception {

        ServerSocket server = null;
        try 
        {
            server = new ServerSocket(5000);
        } 
        catch (IOException e) 
        {
            System.out.println("Error on port: 5000 " + ", " + e);
            System.exit(1);
        }

        System.out.println("Server setup and waiting for client connection ...");

        Socket client = null;
        try 
        {
            client = server.accept();
        } 
        catch (IOException e) 
        {
            System.out.println("Did not accept connection: " + e);
            System.exit(1);
        }

        System.out.println("Client connection accepted. Moving to local port     ...");

        try
        {
            InputStream inStream = client.getInputStream();
            AddressBook addressBook = AddressBook.parseDelimitedFrom(inStream);
            Print(addressBook);
            in.close();
            client.close();
            server.close();
        }
        catch(IOException e)
        { System.out.println("IO Error in streams " + e);
        e.printStackTrace();}
    }
}

      

+3


source to share


1 answer


OK. I have read the documentation.

int size = address_book.ByteSize();
char * buffer = new char[size];
address_book.SerializeToArray(buffer, size);

      

Creates a message complete with the size of the message. The message is not a string. It's a packed mess of what it takes to get a message as little as possible.

iResult = send(ConnectSocket, buffer, (int)strlen(buffer), 0);

      



Sends the message up to the first zero embedded in the buffer or after the buffer if the buffer contains no zeros. You will most likely send too much or too little.

Fortunately, you already know the message size size

.

iResult = send(ConnectSocket, buffer, size, 0);

      

I have to do it.

+3


source







All Articles