快速入门

本指南将通过一个简单的示例,帮助您在 iOS 平台 (Objective-C) 上快速开始使用 gRPC。

快速入门

本指南将通过一个简单的示例,帮助您在 iOS 平台 (Objective-C) 上快速开始使用 gRPC。

开始之前

系统要求

  • macOS 10.11 (El Capitan) 或更高版本
  • iOS 7.0 或更高版本

前提条件

  • CocoaPods 1.0 或更高版本

    检查系统上的 CocoaPods 状态和版本

    pod --version
    

    如果 CocoaPods 未安装,请按照 CocoaPods 安装说明 进行安装。

  • Xcode 7.2 或更高版本

    通过 Launchpad 运行 Xcode,然后在菜单中选择 Xcode > About Xcode 来检查您的 Xcode 版本。

    确保已安装命令行开发者工具

    xcode-select --install
    
  • Homebrew

  • autoconf, automake, libtool, pkg-config

    brew install autoconf automake libtool pkg-config
    

下载示例

您需要获取示例应用源代码的本地副本才能完成本快速入门。从 GitHub 仓库 复制源代码

git clone --recursive -b v1.71.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc

安装 gRPC 插件和库

cd grpc
make
[sudo] make install

安装 protoc 编译器

brew tap grpc/grpc
brew install protobuf

运行服务器

对于此示例应用,我们需要在本地机器上运行一个 gRPC 服务器。gRPC Objective-C API 支持创建 gRPC 客户端,但不包含 gRPC 服务器。因此,我们将构建并运行同一仓库中的 C++ 服务器

cd examples/cpp/helloworld
make
./greeter_server &

运行客户端

生成客户端库和依赖项

让 CocoaPods 根据我们的 .proto 文件生成并安装客户端库,同时安装几个依赖项

cd ../../objective-c/helloworld
pod install

(这可能需要编译 OpenSSL,如果 Cocoapods 在您计算机的缓存中还没有它,这会花费大约 15 分钟。)

运行客户端应用

打开 CocoaPods 创建的 Xcode 工作空间

open HelloWorld.xcworkspace

这将使用 Xcode 打开应用项目。通过点击 Xcode 窗口左上角的“运行”按钮,在 iOS 模拟器中运行该应用。您可以在 main.m 中查看调用代码,并在 Xcode 的控制台中查看结果。

代码向本地服务器发送一个包含字符串“Objective-C”的 HLWHelloRequest。服务器响应一个 HLWHelloResponse,其中包含字符串“Hello Objective-C”,然后将其输出到控制台。

恭喜!您刚刚成功运行了一个使用 gRPC 的客户端-服务器应用。

更新 gRPC 服务

现在我们来看看如何更新应用,在服务器上添加一个供客户端调用的额外方法。我们的 gRPC 服务是使用 Protocol Buffers 定义的;您可以在 Protocol Buffers 的 网站 上找到更多关于如何在 .proto 文件中定义服务的信息。目前您只需要知道,服务器和客户端“stub”都有一个名为 SayHello 的 RPC 方法,该方法接收客户端的 HelloRequest 参数,并从服务器返回 HelloResponse,此方法定义如下

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

让我们更新它,使 Greeter 服务有两个方法。编辑 examples/protos/helloworld.proto 文件,添加一个新的 SayHelloAgain 方法,使用相同的请求和响应类型

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

记得保存文件!

更新客户端和服务器

现在我们有了一个新的 gRPC 服务定义,但我们仍然需要在示例应用的手写部分实现和调用新方法。

更新服务器

如您所知,gRPC 不提供 Objective-C 的服务器 API。相反,我们需要更新 C++ 示例服务器。打开 examples/cpp/helloworld/greeter_server.cc。像这样实现新方法

class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
  Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello again ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
};

更新客户端

编辑 examples/objective-c/helloworld/main.m 中的 main 函数,像这样调用新方法

int main(int argc, char * argv[]) {
  @autoreleasepool {
    HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress];

    HLWHelloRequest *request = [HLWHelloRequest message];
    request.name = @"Objective-C";

    GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
    // this example does not use TLS (secure channel); use insecure channel instead
    options.transport = GRPCDefaultTransportImplList.core_insecure;
    options.userAgentPrefix = @"HelloWorld/1.0";

    [[client sayHelloWithMessage:request
                 responseHandler:[[HLWResponseHandler alloc] init]
                     callOptions:options] start];
    [[client sayHelloAgainWithMessage:request
                      responseHandler:[[HLWResponseHandler alloc] init]
                          callOptions:options] start];

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
  }
}

构建并运行

首先终止后台正在运行的服务器进程

pkill greeter_server

然后在目录 examples/cpp/helloworld 中,使用以下命令构建并运行更新后的服务器

make
./greeter_server &

将目录更改为 examples/objective-c/helloworld,然后使用以下命令清除并重新安装客户端应用的 Pods

rm -Rf Pods
rm Podfile.lock
rm -Rf HelloWorld.xcworkspace
pod install

这将根据我们上面编写的新 proto 文件重新生成 Pods/HelloWorld 中的文件。在 Xcode 中打开客户端 Xcode 项目

open HelloWorld.xcworkspace

并运行客户端应用。如果查看控制台消息,您将看到两个 RPC 调用,一个调用 SayHello,一个调用 SayHelloAgain。

故障排除

安装 CocoaPods 时,出现错误 activesupport requires Ruby version >= 2.2.2

安装旧版本的 activesupport,然后安装 CocoaPods

[sudo] gem install activesupport -v 4.2.6
[sudo] gem install cocoapods
使用 CocoaPods 安装依赖项时,出现错误 Unable to find a specification for !ProtoCompiler-gRPCPlugin

通过运行 pod repo update 更新本地 spec 仓库的克隆

编译 objective_c_plugin.cc 时出现编译错误

在构建 gRPC 之前使用 Homebrew 移除 protobuf 包可能会解决此问题。我们正在研究一个更优雅的修复方案。

构建 HellowWorld 时,出现错误 ld: unknown option: --no-as-needed

此问题是由于 Apple LLVM 中的链接器 ld 不支持 --no-as-needed 选项导致的。我们目前正在修复此问题,并将很快合并修复方案。

构建 grpc 时,出现错误 cannot find install-sh install.sh or shtool

移除 gRPC 目录,重新克隆一份并重试。很可能是一些自动生成的文件损坏了;移除并重新构建可能会解决此问题。

构建 grpc 时,出现错误 Can't exec "aclocal"

缺少软件包 automake。安装 automake 应该可以解决此问题。

构建 grpc 时,出现错误 possibly undefined macro: AC_PROG_LIBTOOL

缺少软件包 libtool。安装 libtool 应该可以解决此问题。

构建 grpc 时,出现错误 cannot find install-sh, install.sh, or shtool

部分自动生成的文件已损坏。移除整个 gRPC 目录,从 GitHub 克隆一份,然后重新构建。

构建 HelloWorld 时找不到 protoc

运行 brew install protobuf 来获取 protoc 编译器。

下一步