Go 和 C++ 程序通过 protobuf 来进行数据交互

介绍

这篇文章主要介绍如何使用 Protobuf 来在 Go 语言程序和 C++ 程序之间进行数据交互。
这里使用 Go 编写服务端,而用 C++ 编写客户端。

编写 proto 协议文件

在开始写客户端和服务端之前,首先需要生成 Go 和 C++ 的 proto 协议文件,只编写一个 proto 文件即可。
新建一个名为 msg.proto 的文件,输入如下内容:

syntax = "proto3";
package msg;

message Msg {
    int64 MsgId = 1;
    string MsgInfo = 2;
    string MsgFrom = 3;
}

编译 proto 文件

执行下列命令分别生成 Go 语言和 C++ 对应的文件

protoc --cpp_out=. msg.proto
protoc --go_out=. msg.proto

编写 Go 服务端程序

package main
import (
    "fmt"
    "os"
    "net"
    
    "test/msg"
    
    "github.com/google/protobuf/proto"
)
func handleConn(conn net.Conn) {
    defer conn.Close()
    buf := make([]byte, 128)
    n, err := conn.Read(buff)
    if err != nil {
        fmt.Println("read data failed...")
        return
    }
    fmt.Printf("read len: %d\n", ReadLen)
    fmt.Println(buff)
    
    msgBuf := buf[0 : n]
    reciveMsg := &msg.Msg {}
    
    err = proto.Unmarshal(msgBuf, reciveMsg)
    if err != nil {
        fmt.Printf("unmarshaling error: ", reciveMsg)
    }
    fmt.Printf("msg id: %d\n", reciveMsg.GetMsgId())
    fmt.Printf("msg info: %s\n", reciveMsg.GetMsgInfo())
    fmt.Printf("msg from id: %s\n", reciveMsg.GetMsgFrom())
}

func main() {
    tcpAddr, err := net.ResolveTCPAddr("tcp4", ":2121")
    if err != nil {
        fmt.Println("get tcp addr failed...")
        return
    }
    listener, err := net.ListenTCP("tcp", tcpAddr)
    if err != nil {
        fmt.Println("listen tcp failed...")
        return
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        go handleConn(conn)
    }
}

编写 C++ 客户端程序

#include "msg.pb.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <cstring>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char *argv[]){
    
    int sk = socket(AF_INET, SOCK_STREAM, 0);
    
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(2121); // 固定端口port
    server.sin_addr.s_addr = inet_addr("127.0.0.1"); // 固定ip
    
    connect(sk, (struct sockaddr*)&server, sizeof(server));
    
    msg::Msg sendMsg;
    sendMsg.set_msgid(0);
    sendMsg.set_msginfo("hello protobuf");
    sendMsg.set_msgfrom("alex");
    
    string sendData;
    sendMsg.SerializeToString(&sendData);
    int len = sendData.length();
    cout << "string len:" << len << endl;
    
    char *buff = new char[len + 1];
    memcpy(buff, sendData.c_str(), len);
    
    cout << "buff len:" << strlen(buff) << endl;
    //向服务段发送数据
    //在发送数据时一定要指明数据长度 防止中间有\0截断c风格字符串
    send(sk, buff, len, 0);
    close(sk);
    return 0;
}

运行

先后启动服务端和客户端程序

    原文作者:juniway
    原文地址: https://www.jianshu.com/p/76915a6455f1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞