随笔 - 313  文章 - 29  评论 - 32  阅读 - 124万 

在chromium的进程之间使用ipc+protobuffer的方式通信,这样既能保证对模块松耦合,又可以保证独立运行时不会相互被影响。

主要用于以下两个方面:

  • browser进程和系统适配层之间的通信;(包括:音视频播放器或者走行规制相关的接口等)
  • browser进程和render进程之间的通信。

只看代码没有什么帮助,下面写一个demo来模拟这个过程。
本文主要内容转载自:https://blog.csdn.net/niu91/article/details/114995147
感谢道友“牛不才”的文章,让我少走很多弯路。

一、环境列表

Ubuntu 18.04
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
cmake version 3.20.0-rc1
libprotoc 3.6.1
rpc v1.12.0

二、环境准备

  1. 准备rpc
git clone -b v1.12.0 https://gitee.com/niubucai/grpc.git
cd grpc/ 
git tag 
git checkout v1.12.0
git submodule sync 
git submodule update --init
  1. 准备protobuffer
#当前目录是grpc/
cd third_party/protobuf
git tag
git checkout v3.6.1
./autogen.sh 
./configure
sudo make -j4
sudo make install
sudo ldconfig     
protoc --version  
  1. 编译安装grpc
#当前目录是grpc/third_party/protobuf
cd ../../  #回到grpc/
make HAS_SYSTEM_PROTOBUF=false 
sudo make install 
  1. 测试
终端1ubuntu:~/grpc$ cd examples/cpp/helloworld/
ubuntu:~/grpc/examples/cpp/helloworld$ ./greeter_server 
Server listening on 0.0.0.0:50051
终端2ubuntu:~/grpc/examples/cpp/helloworld$ ./greeter_client 
Greeter received: Hello world

三、写一个用unix socket的demo

随便创建一个目录mycode,下面都在这个目录中操作。

  1. 定义服务接口和消息类型到.proto文件中

hello.proto

syntax = "proto3";

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}
  1. 实现服务端代码

server.cc

#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "hello.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;

class HelloServiceImpl final : public HelloService::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloResponse* reply) override {
    std::string prefix("Hi ");
    reply->set_reply(prefix + request->greeting());
    return Status::OK;
  }
};

int main(int argc, char** argv) {
  std::string server_address("unix:/tmp/hello.sock");
  HelloServiceImpl service;

  ServerBuilder builder;
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  builder.RegisterService(&service);
  std::unique_ptr<Server> server(builder.BuildAndStart());
  server->Wait();
  return 0;
}
  1. 实现客户端代码

client.cc

#include <grpcpp/grpcpp.h>
#include "hello.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;

int main(int argc, char** argv) {
  std::string target("unix:/tmp/hello.sock");
  HelloService::Stub stub(grpc::CreateChannel(target, grpc::InsecureChannelCredentials()));

  HelloRequest request;
  HelloResponse reply;
  ClientContext context;

  request.set_greeting("world");

  Status status = stub.SayHello(&context, request, &reply);

  if (status.ok()) {
    std::cout << "Greeter received: " << reply.reply() << std::endl;
  } else {
    std::cout << status.error_code() << ": " << status.error_message()
              << std::endl;
  }

  return 0;
}
  1. 实现Makefile
HOST_SYSTEM = $(shell uname | cut -f 1 -d_)
SYSTEM ?= $(HOST_SYSTEM)
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++17
ifeq ($(SYSTEM),Darwin)
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
           -lgrpc++_reflection\
           -ldl
else
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
           -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
           -ldl
endif
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

PROTOS_PATH = ./

vpath %.proto $(PROTOS_PATH)

all: client server

client: hello.pb.o hello.grpc.pb.o client.o
        $(CXX) $^ $(LDFLAGS) -o $@

server: hello.pb.o hello.grpc.pb.o server.o
        $(CXX) $^ $(LDFLAGS) -o $@

.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
        $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<

.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
        $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $<

clean:
        rm -f *.o *.pb.cc *.pb.h client server

从Makefile中可以看出,protoc命令通过类似下面的形式生成了hello.pb.h、hello.pb.c、hello.grpc.pb.h、hello.grpc.pb.c等文件。

protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` hello.proto
protoc --cpp_out=. hello.proto
  1. 编译测试
#编译
make
#终端1
$ ./server
#终端2
$ ./client
Greeter received: Hi world

四、问题及解决方法

  1. 找不到protoc-gen-grpc命令?
    首先看下/usr/local/bin目录下是否有可执行文件protoc-gen-grpc,如果有,把/usr/local/bin添加到$PATH中就行了
export PATH="/usr/local/bin:$PATH"

如果没有,那么重新编译一下grpc

cd grpc/cmake
mkdir build
cd build
cmake ../..
make -j4
make install

再次查看/usr/local/bin中是否有protoc-gen-grpc?
如果有,把/usr/local/bin添加到$PATH中,
如果没有,把grpc/cmake/build/protoc-gen-grpc文件复制到/usr/local/bin/中,把/usr/local/bin添加到$PATH中。

2.zlib.h找不到
我没遇到此问题。

wget http://www.zlib.net/zlib-1.2.11.tar.gz
tar -xvf zlib-1.2.11.tar.gz
cd zlib-1.2.11/
./configure
make
sudo make install

3.编译报错more undefined references to grpc::g_core_codegen_interface' follow collect2: error: ld returned 1 exit status`
Makefile中的路径、文件什么的没配好,检查一下Makefile,核对一下各个模块的版本是否可以对应上。
.gitmodules 文件

[submodule "third_party/zlib"]
        path = third_party/zlib
        url = https://github.com/madler/zlib
        # When using CMake to build, the zlib submodule ends up with a
        # generated file that makes Git consider the submodule dirty. This
        # state can be ignored for day-to-day development on gRPC.
        ignore = dirty
[submodule "third_party/protobuf"]
        path = third_party/protobuf
        url = https://github.com/google/protobuf.git
        branch = 3.0.x
[submodule "third_party/gflags"]
        path = third_party/gflags
        url = https://github.com/gflags/gflags.git
[submodule "third_party/googletest"]
        path = third_party/googletest
        url = https://github.com/google/googletest.git
[submodule "third_party/boringssl"]
        path = third_party/boringssl
        url = https://github.com/google/boringssl.git
[submodule "third_party/benchmark"]
        path = third_party/benchmark
        url = https://github.com/google/benchmark
[submodule "third_party/boringssl-with-bazel"]
        path = third_party/boringssl-with-bazel
        url = https://github.com/google/boringssl.git
[submodule "third_party/cares/cares"]
        path = third_party/cares/cares
        url = https://github.com/c-ares/c-ares.git
        branch = cares-1_12_0
[submodule "third_party/bloaty"]
        path = third_party/bloaty
        url = https://github.com/google/bloaty.git
[submodule "third_party/abseil-cpp"]
        path = third_party/abseil-cpp
        url = https://github.com/abseil/abseil-cpp
posted on   步孤天  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
历史上的今天:
2019-12-12 Bash Shell如何实现动态变量
点击右上角即可分享
微信分享提示