首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从C++向Java发送原型

从C++向Java发送原型
EN

Stack Overflow用户
提问于 2015-06-12 01:09:36
回答 1查看 5.9K关注 0票数 3

我试图通过套接字将C++应用程序的protobuf发送到Java应用程序。我正在使用一个简单的套接字在mu C++程序上发送原型。在通过网络发送它之前,我已经将其序列化到char缓冲区。在我的Java(服务器)程序中,我使用ServerSocket接收数据。

我很难在Java端反序列化protobuf。它不断地给我带来错误:

  1. 在解析协议消息时,输入意外地结束在字段的中间。这可能意味着输入已经被截断,或者嵌入的消息错误地报告了自己的长度。
  2. CodedInputStream遇到了畸形的静脉曲张。

我做错了什么?我的密码在下面。

原型示例取自Google的教程- AddressBook.proto教程

C++代码:

代码语言:javascript
复制
#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程序:

代码语言:javascript
复制
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();}
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-12 06:25:03

好的。我看了文件。

代码语言:javascript
复制
int size = address_book.ByteSize();
char * buffer = new char[size];
address_book.SerializeToArray(buffer, size);

生成具有邮件大小的消息。消息不是字符串。这是一堆乱七八糟的东西,为了得到尽可能小的信息。

代码语言:javascript
复制
iResult = send(ConnectSocket, buffer, (int)strlen(buffer), 0);

如果缓冲区不包含任何空值,则将消息发送到嵌入缓冲区中的第一个null或缓冲区后。你很可能寄得太多或太少。

幸运的是,您已经知道消息的大小:size

代码语言:javascript
复制
iResult = send(ConnectSocket, buffer, size, 0);

应该这么做。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30793848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档