注意:这里是不通过proto.exe 生成一系列js文件 实现的。
1 npm init --建立项目
2 安装protoc以及grpc插件
npm install grpc-tools --save-dev
npm install google-protobuf --save
npm install grpc --save
注意:完成后 需要保证在node-modules文件下有grpc-tools文件
如果没有 使用 npm -i grpc-tools 进行安装。 grpc-tools 后面要用来加载proto文件
package.json
{
"name": "grpc-node",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@grpc/proto-loader": "^0.1.0",
"async": "^1.5.2",
"google-protobuf": "^3.0.0",
"grpc": "^1.11.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}
}
也可以直接把 package.json 文件复制到项目 进行npm install。
3 直接上代码
HelloWorld.proto
syntax = "proto3";
option java_package = "ex.grpc";
option objc_class_prefix = "HSW";
package helloworld; //后面需要加载这个package
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc printAge (printAgeRequest) returns (printAgeReply) {}
}
message HelloRequest {
string name = 1;
string city = 2;
}
message HelloReply {
string message = 1;
}
message printAgeRequest {
string age = 1;
}
message printAgeReply {
string text = 1;
}
client.js
const path = require('path');
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
const PROTO_PATH = path.resolve(__dirname, './HelloWorld.proto');
const packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; //引用proto文件内容package
function main() {
console.log('client start.......')
// 调用 Greeter 的存根构造函数,指定服务器地址和端口。
const client = new hello_proto.Greeter( '127.0.0.1:50051', grpc.credentials.createInsecure());
// 构造调用服务的方法:使用事件或者回调函数去获得结果
function getMessage(error, response) {
if (error) {
console.log(error);
return;
}
console.log('Greeting: ', response.message)
}
function getText(error, response) {
if (error) {
console.log(error);
return;
}
console.log('Text is : ', response.text)
}
// 调用存根上的方法,传入请求和回调函数
client.sayHello({name: 'locy', city: '上海'}, getMessage);
client.printAge({age: '45'}, getText)
}
main()
server.js
const path = require('path');
const grpc = require('grpc');
const protoLoader = require('@grpc/proto-loader');
// 从 proto 文件加载服务描述符
const PROTO_PATH = path.resolve(__dirname, './HelloWorld.proto');
const packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
}
);
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
// SayHello的实现,调用call.request为protobuf文件的请求体,将返回体通过callback函数回传至客户端。
function sayHello2(call, callback) {
try {
let data = 'hello ' + call.request.name + ' and city is ' + call.request.city;
callback && callback(null, {message: data})
} catch (err) {
console.log('错误');
callback && callback(err)
}
}
function printAge2(call, callback) {
try{
let text = 'current age is ' + call.request.age;
callback && callback(null, {text})
} catch (err) {
console.log('错误');
callback && callback(err)
}
}
// 服务器的启动方法
/*
1、通过 Greeter 服务描述符创建一个 Server 构造函数。
2、实现服务的方法。
3、通过调用 Server 的构造函数以及方法实现去创建一个服务器的实例。
4、用实例的 bind() 方法指定地址以及我们期望客户端请求监听的端口。
5、调用实例的 start() 方法启动一个RPC服务器。
*/
function main() {
const server = new grpc.Server();
server.addService(hello_proto.Greeter.service, {
SayHello: sayHello2,
printAge: printAge2
});
server.bind('127.0.0.1:50051', grpc.ServerCredentials.createInsecure());
server.start();
console.log('server start......')
}
main()
四
依次启动 node server.js
node client.js
五 文件目录结构如下