go使用protobuf和cpp进行tcp通信

4 篇文章 1 订阅

msg.proto

syntax = "proto3";

package MSG;
option go_package = ".;MSG";

message Person {
  string name = 1;
  int32 id = 2;  
  string email = 3;
}

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


func Marshal(m Message) ([]byte, error)
func Unmarshal(b []byte, m Message) error
type Message = protoreflect.ProtoMessage
type ProtoMessage interface{ ProtoReflect() Message }
go_server.go

/*
func (m selfMarshaler) Marshal() ([]byte, error)
func (m *selfMarshaler) Unmarshal(b []byte) error
*/
package main

import (
    "MSG"
    "fmt"

    //"github.com/golang/protobuf/proto"
    "net"
    "os"

    "google.golang.org/protobuf/proto"
    "google.golang.org/protobuf/reflect/protoreflect"
)

func main() {
    serve, err := net.Listen("tcp", "127.0.0.1:9999")
    if err != nil {
        fmt.Println("Error: %s", err.Error())
        os.Exit(1)
    }
    fmt.Println("listen on 127.0.0.1:9999")

    for {
        conn, err := serve.Accept() // 建立连接
        if err != nil {
            fmt.Println("accept failed, err:", err)
            continue
        }
        fmt.Printf("new client %s %d\n", conn.RemoteAddr().(*net.TCPAddr).IP,
            conn.RemoteAddr().(*net.TCPAddr).Port)

        p := MSG.Person{
            Name:  "qwe",
            Id:    1,
            Email: "1234343@qq.com",
        }

        b, err := Encode(&p) //proto.Marshal(&p)
        if err != nil {
            fmt.Println("proto err ", err)
            break
        }

        //Write(b []byte) (n int, err error)
        _, err = conn.Write(b)
        if err != nil {
            fmt.Println("send err ", err)
            break
        }
        conn.Close()
    }

}

func Encode(msgObj interface{}) ([]byte, error) {

    return proto.Marshal(msgObj.(protoreflect.ProtoMessage))
}


go_client.go

package main

import (
    "MSG"
    "fmt"

    //"github.com/golang/protobuf/proto"
    "net"
    "os"

    "google.golang.org/protobuf/proto"
    "google.golang.org/protobuf/reflect/protoreflect"
)

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:9999")
    if err != nil {
        fmt.Println("Error: %s", err.Error())
        os.Exit(1)
    }
    fmt.Println("connect ok")
    defer conn.Close()

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println("conn closed")
        return
    }

    ss := new(MSG.Person)
    err = Decode(buf[0:n], ss) //proto.Unmarshal(buf[0:n], ss)
    if err != nil {
        fmt.Println("proto.Unmarshal error")
        return
    }
    fmt.Println(ss)
    fmt.Println(ss.Name, ss.Id, ss.Email)
}

// 将pb的字节数组解码为结构体
func Decode(data []byte, msgObj interface{}) error {

    return proto.Unmarshal(data, msgObj.(protoreflect.ProtoMessage))
}


cpp_server.cpp

/*
g++ -std=c++11 -o cpp_server cpp_server.cpp msg.pb.cc -I/usr/local/include/google/protobuf -lprotobuf -lpthread
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>

#include "msg.pb.h"

using namespace std;

int main(int argc,char *argv[])
{
    int server_sock, client_sock, r;
    struct sockaddr_in server_addr, client_addr;
    socklen_t len;
    if(argc!=2)
    {
        printf("need port\n");
        return 1;
    }
    int port = atoi(argv[1]);
    server_sock = socket(AF_INET,SOCK_STREAM,0);
    memset(&server_addr, 0, sizeof server_addr);
    server_addr.sin_family=AF_INET;
    server_addr.sin_addr.s_addr=inet_addr("0.0.0.0");//htonl(INADDR_ANY)
    server_addr.sin_port=htons(port);
    if(-1 == bind(server_sock, (struct sockaddr*)&server_addr,sizeof(server_addr)))
    {
        printf(" bind error\n");
        return -1;
    }
    if(-1 == listen(server_sock, 10))
    {
        printf(" listen error\n");
        return -1;
    }
    printf("listen on %d\n",port);

    client_sock = accept(server_sock,(struct sockaddr*)&client_addr,&len);
    assert(client_sock > 0);

    MSG::Person p;
    p.set_name("李四");
    p.set_id(1);
    p.set_email("36985695@qq.com");

    string buf;
    p.SerializeToString(&buf);

    r = write(client_sock, buf.c_str(), buf.length());
    assert(r == buf.length());

    cout<<"send ok"<<endl;
    close(client_sock);
    close(server_sock);
    return 0;
}
/*
r = read(client_sock,buf,SIZE);
    buf[r] = '\0';
    string s = buf;
    printf("read r=%d, s.length()=%ld\n", r, s.length());

    //解析客户端发来的数据
    MSG::Person people;
    people.ParseFromString(s);
    cout<<people.name()<<" "<<people.id()<<" "<<people.email()<<endl; 
*/

编译

[gdut17@localhost protobuf]$ g++ -std=c++11 -o cpp_server cpp_server.cpp msg.pb.cc -I/usr/local/include/google/protobuf -lprotobuf -lpthread
[gdut17@localhost protobuf]$ ./cpp_server 9999 
listen on 9999
send ok

[gdut17@localhost protobuf]$ go build go_client.go 
[gdut17@localhost protobuf]$ ./go_client 
connect ok
name:"李四"  id:1  email:"36985695@qq.com"


原文链接:https://blog.csdn.net/beyond706/article/details/109155752

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值