problem
In the development of mobile applications, will usually achieve complex business logic on the server, the client is only responsible for the presentation layer. But for some mobile phone applications, business logic located on the server but is unsafe or unreasonable, but it needs to be realized directly on the phone logical end.
purpose
Face different mobile client systems, separate repeated to achieve the same business logic, not best practices. How will form a third-party language Go language business logic is encapsulated into a library, and a static packed way to provide mobile client to use different systems, it is the purpose of this survey.
Ideal goal graph:
Specific research contents include:
- [the X-] iOS applications to achieve gRPC call
- [the X-] Android application implements gRPC call
- [] GoMobile SDK integrated on the iOS & Android
- [] GoMobile SDK boundary on the iOS & Android
- [] C / S architecture or static library
About gRPC in which to achieve iOS and Android, the official in itself has provided a sample. The survey will use the relevant content, so it will be recorded as part of research to facilitate the later ones to read. All involved in the research project code are stored in: liujianping / GRPC-Apps warehouse, a friend in need can be downloaded directly tested.
In the original release my personal site: GitDiG.com description link:. IOS applications to achieve gRPC call .
1. Installation Environment
As a part-time iOS programmers often need to research unfamiliar technology or language. The first is to overcome the psychological fear of the unknown. In fact, a lot of things not so difficult, just need to start it. In order to complete the research objectives, the first part of the research work began. Be recorded in written form, to facilitate newcomers.
1.1 XCode installation
Nothing to say, direct AppStore download and install. A bit slow, while downloading prepare other environments.
1.2 Cocoapod installation
Like any other language, third-party database management tool. I have nothing to say, visit the official website, follow the instructions to install.
$: sudo gem install cocoapods
1.3 protoc command to install
Because of the widespread use gRPC, protobuf byte protocol is widely used for encoding and decoding protocol, with reference to the specific guidelines [official website] (). Man of few words said, the installation:
$: curl -LOk https://github.com/protocolbuffers/protobuf/releases/download/v3.5.1/protoc-3.9.0-rc-1-osx-x86_64.zip
$: unzip protoc-3.9.0-rc-1-osx-x86_64.zip -d proto_buffer && cd proto_buffer
$: sudo cp bin/protoc /usr/local/bin
$: sudo cp -R include/google/protobuf/ /usr/local/include/google/protobuf
$: protoc --version
1.4 protoc plug-in installation
protoc mainly by parsing the .proto
file format and then generates a corresponding language code according to the specific widget.
Taking into account the need to implement the code client and server, so you must install the following three plug-ins:
- swift
- swiftgrpc
- go go mainly generated code to implement the service side
swift plug-in installed:
$: git clone https://github.com/grpc/grpc-swift.git
$: cd grpc-swift
$: git checkout tags/0.5.1
$: make
$: sudo cp protoc-gen-swift protoc-gen-swiftgrpc /usr/local/bin
go plug-in installed:
Provided that the need to install the Go language development environment, refer to the official website. protoc-gen-go
Detailed installation guide .
$: go get -u github.com/golang/protobuf/protoc-gen-go
2 proto-defined interfaces
Since it is the most simple research on the use of the most simple Hello service. Create a project and define the path:
$: mkdir grpc-apps
$: cd grpc-apps
$: mkdir proto
$: cat <<EOF > proto/hello.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.gitdig.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
EOF
3. Service-side implementation
Create a server directory in the project directory and proto build directory, and write a simple server:
$: cd grpc-apps
$: mkdir go go/client go/server go/hello
# 生成 Go 代码到 go/hello 文件夹
$: protoc -I proto proto/hello.proto --go_out=plugins=grpc:./go/hello/
Go to edit both versions of client and server implementation. Confirm service is operating normally.
3.1 Go server
Edit server/server.go
the file:
package main
import (
pb "github.com/liujianping/grpc-apps/go/helloworld"
)
import (
"context"
"fmt"
"log"
"net"
"google.golang.org/grpc"
)
type HelloServer struct{}
// SayHello says 'hi' to the user.
func (hs *HelloServer) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
// create response
res := &pb.HelloReply{
Message: fmt.Sprintf("hello %s from go", req.Name),
}
return res, nil
}
func main() {
var err error
// create socket listener
l, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("error: %v\n", err)
}
// create server
helloServer := &HelloServer{}
// register server with grpc
s := grpc.NewServer()
pb.RegisterGreeterServer(s, helloServer)
log.Println("server serving at: :50051")
// run
s.Serve(l)
}
Run the server program:
$: cd grpc-apps/go
$: go run server/server.go
2019/07/03 20:31:06 server serving at: :50051
3.2 Go client
Edit client/client.go
the file:
package main
import (
pb "github.com/liujianping/grpc-apps/go/helloworld"
)
import (
"context"
"fmt"
"log"
"google.golang.org/grpc"
)
func main() {
var err error
// connect to server
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("error: %v\n", err)
}
defer conn.Close()
// create client
client := pb.NewGreeterClient(conn)
// create request
req := &pb.HelloRequest{Name: "JayL"}
// call method
res, err := client.SayHello(context.Background(), req)
if err != nil {
log.Fatalf("error: %v\n", err)
}
// handle response
fmt.Printf("Received: \"%s\"\n", res.Message)
}
Execute client program:
$: cd grpc-apps/go
$: go run client/client.go
Received: "hello JayL from go"
Go client / server communication is successful.
4. iOS project
4.1 to create a simple single-view project
Create a project called iosDemo single view, select swift language, storage path on the grpc-apps
next. When you finish creating, running, exit the program.
4.2 Project Initialization Pod
In the command line initialization:
$: cd grpc-apps/iosDemo
# 初始化
$: pod init
$: vim Podfile
Edit Podfile as follows:
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'iosDemo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for iosDemo
pod 'SwiftGRPC'
end
When you finish editing save, run the install command:
$: pod install
After installation is complete, the project directory happen the following changes:
$: git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: iosDemo.xcodeproj/project.pbxproj
Untracked files:
(use "git add <file>..." to include in what will be committed)
Podfile
Podfile.lock
Pods/
iosDemo.xcworkspace/
no changes added to commit (use "git add" and/or "git commit -a")
The command line open iosDemo.xcworkspace
to open the project, the following settings in the project info.list be modified:
By setting, open a non-secure HTTP access.
4.3 Code generation gRPC swift
Similarly Go code generation, now swift generate the code:
$: cd grpc-apps
# 创建生成文件存放目录
$: mkdir swift
# 生成 swift 文件
$: protoc -I proto proto/hello.proto \
--swift_out=./swift/ \
--swiftgrpc_out=Client=true,Server=false:./swift/
# 生成文件查看
$: tree swift
swift
├── hello.grpc.swift
└── hello.pb.swift
4.4 generates code integrated into the iOS project
XCode generate the code needed to add by dragging the way for back-end development, it is a bit unreasonable. But since so we must follow the rules:
Now add gRPC call a procedure in view loading function for iOS:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let client = Helloworld_GreeterServiceClient(address: ":50051", secure: false)
var req = Helloworld_HelloRequest()
req.name = "JayL"
do {
let resp = try client.sayHello(req)
print("resp: \(resp.message)")
} catch {
print("error: \(error.localizedDescription)")
}
}
}
View the log output resp: hello iOS from go
, the successful iOS application calls gRPC service.