012 rust network programming, grpc demonstration example

Time:2021-3-8

Presentation

The function of this example is that grpc client writes location information to server and reads location information. The demo environment is Ubuntu.

preparation

To install the protobuf compiler:

apt install protobuf-compiler

Demonstration examples

New projects

cargo new use_ Grpc -- lib # remember the name use_ Grpc, because you need to use it when you write code

New proto file

In use_ Grpc directory, create foobar.proto The code is as follows:

syntax = "proto3";

package foobar;

service FooBarService {
    rpc record_cab_location(CabLocationRequest) returns (CabLocationResponse);
    rpc get_cabs(GetCabRequest) returns (GetCabResponse);
}

message CabLocationRequest {
    string name = 1;
    Location location = 2;
}

message CabLocationResponse {
    bool accepted = 1;
}

message GetCabRequest {
    Location location = 1;
}

message GetCabResponse {
    repeated Cab cabs = 1;
}

message Cab {
    string name = 1;
    Location location = 2;
}

message Location {
    float latitude = 1;
    float longitude = 2;
}

Create build script

In use_ Grpc directory, create build.rs File, edited as follows:

extern crate protoc_rust_grpc;

fn main() {
    protoc_rust_grpc::Codegen::new()
    .out_dir("src")
    .input("foobar.proto")
    .rust_protobuf(true)
    .run()
    .expect("protoc-rust-grpc");
}

to write Cargo.toml file

Add the following to the file:

 [dependencies]
protobuf = "2"
grpc = "0.7.1"
grpc-protobuf = "0.7.1"
futures = "0.3.*"
tls-api = "0.3.*"

[build-dependencies]
protoc-rust-grpc = "0.7.1"

[[bin]]
name = "client"
test = false

[[bin]]
name = "server"
test = false

Write the source code

to write lib.rs

Write SRC directory lib.rs , as follows:

pub mod foobar;
pub mod foobar_grpc;

Write server

Create bin directory in SRC directory, and create bin directory in bin directory server.rs It is written as follows:

use std::thread;

use use_ grpc::foobar_ grpc::*;//use_ Grpc is the name of the current package. If the name is different, it needs to be modified
use use_ grpc::foobar::*;//use_ Grpc is the name of the current package. If the name is different, it needs to be modified

struct FooBarServer;

impl FooBarService for FooBarServer {
    fn record_cab_location(&self, 
        _o: grpc::ServerHandlerContext, 
        req: grpc::ServerRequestSingle<CabLocationRequest>, 
        resp: grpc::ServerResponseUnarySink<CabLocationResponse>) 
        -> grpc::Result<()>
    {
        let mut r = CabLocationResponse::new();

        println!("Recorded cab {} at {}, {}", req.message.get_name(), req.message.get_location().latitude, req.message.get_location().longitude);

        r.set_accepted(true);
        resp.finish(r)
    }

    fn get_cabs(&self, 
        _o: grpc::ServerHandlerContext, 
        _req: grpc::ServerRequestSingle<GetCabRequest>, 
        resp: grpc::ServerResponseUnarySink<GetCabResponse>)
         -> ::grpc::Result<()>
    {
        let mut r = GetCabResponse::new();

        let mut location = Location::new();
        location.latitude = 40.7128;
        location.longitude = -74.0060;

        let mut one = Cab::new();
        one.set_name("Limo".to_owned());
        one.set_location(location.clone());

        let mut two = Cab::new();
        two.set_name("Merc".to_owned());
        two.set_location(location.clone());

        let vec = vec![one, two];
        let cabs = ::protobuf::RepeatedField::from_vec(vec);

        r.set_cabs(cabs);

        resp.finish(r)
    }
}

fn main() {
    let mut server = grpc::ServerBuilder::new_plain();
    server.http.set_port(9001);
    server.add_service(FooBarServiceServer::new_service_def(FooBarServer));
    // server.http.set_cpu_pool_threads(4);
    let _server = server.build().expect("Could not start server");
    loop {
        thread::park();
    }
}

Write client

Create in Src / bin directory client.rs It is written as follows:

use use_ grpc::foobar::*;//use_ Grpc is the name of the current package. If the name is different, it needs to be modified
use use_ grpc::foobar_ grpc::*;//use_ Grpc is the name of the current package. If the name is different, it needs to be modified
use futures::executor;

use grpc::ClientStubExt;


fn main() {
    let client = 
        FooBarServiceClient::new_plain("127.0.0.1", 
        9001, 
        Default::default())
        .unwrap();

    let mut req = CabLocationRequest::new();
    req.set_name("foo".to_string());

    let mut location = Location::new();
    location.latitude = 40.730610;
    location.longitude = -73.935242;
    req.set_location(location);

    let resp = client
        .record_cab_location(grpc::RequestOptions::new(), req)
        .join_metadata_result();
    let resp = executor::block_on(resp);
    match resp {
        Err(e) => panic!("{:?}", e),
        Ok((_, r, _)) => println!("{:?}", r),
    }

    let mut nearby_req = GetCabRequest::new();
    let mut location = Location::new();
    location.latitude = 40.730610;
    location.longitude = -73.935242;    
    nearby_req.set_location(location);

    let nearby_resp = client
        .get_cabs(grpc::RequestOptions::new(), nearby_req)
        .join_metadata_result();
    let nearby_resp = executor::block_on(nearby_resp);
    match nearby_resp {
        Err(e) => panic!("{:?}", e),
        Ok((_, cabs, _)) => println!("{:?}", cabs),
    }
}

compile

Cargo build // compile

After compiling, the directory structure is as follows:

use_grpc
    |----- build.rs
    |----- Cargo.toml
    |----- foobar.proto
    |----- src
            |----- lib.rs
            |----- foobar_grpc.rs
            |----- foobar.rs
            |----- bin
                    |----- client.rs
                    |----- server.rs

Foobar_ grpc.rs and foobar.rs The file generated for compilation.

function

Enter the target / debug directory.

  • Run the server first
    ./server
  • Run client
    ./client

This work adoptsCC agreementReprint must indicate the author and the link of this article

Linghu Yichong

Recommended Today

Rust and python: why rust can replace Python

In this guide, we compare the rust and python programming languages. We will discuss the applicable use cases in each case, review the advantages and disadvantages of using rust and python, and explain why rust might replace python. I will introduce the following: What is rust? What is Python? When to use rust When to […]