1 hello.proto
syntax = "proto3"; // 声明使用哪一种的protobuf
package test; // 包名称
// 服务 类似视图
service Bibili {
// rpc 服务
rpc HelloYoyo (HelloYoyoRequst) returns (HelloYoyoResponse) {
}
rpc HelloTest (HelloTsetRquest) returns (HelloTestRsponse) {
}
rpc HelloStream (stream HelloTsetRquest) returns (stream HelloTestRsponse) { // 定义流传输
}
rpc TsetClientRectStream (TsetClientRectStreamRequest) returns (stream TsetClientRectStreamRsponse) {
}
rpc TsetClientSendStream (stream TsetClientSendStreamRequest) returns (TsetClientSendStreamRsponse) {
}
rpc TsetTowWayStream (stream TsetTowWayStreamRquest) returns (stream TsetTowWayStreamRsponse) {
}
}
message TsetTowWayStreamRquest {
string data = 1;
}
message TsetTowWayStreamRsponse {
string result = 1;
}
message TsetClientSendStreamRequest {
string data = 1;
}
message TsetClientSendStreamRsponse {
string result = 1;
}
message TsetClientRectStreamRequest {
string data = 1;
}
message TsetClientRectStreamRsponse {
string result = 1;
}
message HelloYoyoRequst {
string name = 1;
int32 age = 2;
}
message HelloYoyoResponse {
string result = 1;
}
message HelloTsetRquest {
string name = 1;
int32 age = 2;
repeated string data = 3;
repeated HelloTsetRsqusetValue lists = 4; // 自己定义数据类型
map<string, int64> number = 5; //注释
map<string, HelloTsetRsqusetValue> value = 6; // 自己定义数据类型
}
message HelloTsetRsqusetValue {
string name = 1;
int32 age = 2;
bool is_active = 3;
}
message HelloTestRsponse {
}
2 service.py
import time
from concurrent import futures # grcp线程
import grpc
import hello_pb2 as pb2
import hello_pb2_grpc as pb2_grcp
def _abort(code, detail):
def terminate(ingnored_request, context):
context.abort(code, detail)
return grpc.unary_unary_rpc_method_handler(terminate)
# 书写一个拦截器
class TestInterceptor(grpc.ServerInterceptor):
def __init__(self, key, value, code, detail):
self.key = key
self.value = value
self._abort = _abort(code, detail)
def intercept_service(self, continuation, handler_call_details):
'''
:param continuation: 函数执行器
:param handler_call_details: header
:return:
'''
if (self.key, self.value) not in handler_call_details.invocation_metadata:
return self._abort
return continuation(handler_call_details)
class Bibili(pb2_grcp.BibiliServicer):
def HelloYoyo(self, request, context):
name = request.name
age = request.age
if name == "yoyo123":
context.set_details("程序出现问题") # 添加一些描述
context.set_code(grpc.StatusCode.DATA_LOSS) # 设置code码
raise context # 抛出异常
context.set_trailing_metadata((("name", "yoyo"), ("key", "vlaue"))) # 给客户端传输消息
headers = context.invocation_metadata() # 接受客户端传输过来的消息
print(headers)
print(headers[0].key, headers[0].value)
result = "my name is {}, i am {} year old".format(name, age)
context.set_compression(grpc.Compression.Gzip) # 数据压缩 只针对这个函数内的内容
return pb2.HelloYoyoResponse(result=result)
def TsetClientRectStream(self, request, context):
index = 0
while context.is_active():
data = request.data
if data == 'close':
print('data is close, request will cancel')
context.cancel() # 关闭
time.sleep(1)
index += 1
yield pb2.TsetClientRectStreamRsponse(result="send{}: {}".format(index, data))
def TsetClientSendStream(self, request_iterator, context):
index = 0
for request in request_iterator:
print(request.data)
if index == 10:
break
index += 1
return pb2.TsetClientSendStreamRsponse(result="ok")
def TsetTowWayStream(self, request_iterator, context):
index = 0
for request in request_iterator:
data = request.data
print(data)
if index == 10:
context.cancel() # 关闭
index += 1
yield pb2.TsetTowWayStreamRsponse(result="service send {}".format(data))
def run():
validator = TestInterceptor("name", "yoyo", grpc.StatusCode.UNAUTHENTICATED, "Access denined")
grpc_server = grpc.server(
futures.ThreadPoolExecutor(max_workers=4), # 设置工作时最大的线程数量
compression=grpc.Compression.Gzip, # 设置压缩, 针对这个服务器所有的内容
interceptors=(validator,),
options=[("grpc.max_send_message_length", 50 * 1024 * 1024), # grpc.max_send_message_length:设置发送数据的最大数量
("grpc.max_receive_message_length", 50 * 1024 * 2014)] # grpc.max_receive_message_length:设置接收数据的最大数量
)
pb2_grcp.add_BibiliServicer_to_server(Bibili(), grpc_server) # 注册Bibili到grpc_server中
grpc_server.add_insecure_port("0.0.0.0:5000") # 绑定ip和端口
print("server will start at 0.0.0.0:5000")
grpc_server.start() # 启动
try:
while 1:
time.sleep(3600) # 堵塞在这里
except KeyboardInterrupt:
grpc_server.stop(0) # 结束
if __name__ == "__main__":
run()
3 client.py
import random
import time
import grpc
import hello_pb2 as pb2
import hello_pb2_grpc as pb2_grpc
def test():
index = 0
while True:
time.sleep(1)
data = str(random.random())
if index == 5:
break
index += 1
yield pb2.TsetClientSendStreamRequest(data=data)
def run():
conn = grpc.insecure_channel("0.0.0.0:5000") # 定义一个频道
client = pb2_grpc.BibiliStub(channel=conn) # 生成客户端
try:
response, call = client.HelloYoyo.with_call(pb2.HelloYoyoRequst(name="yoyo", age=33), compression=grpc.Compression.Gzip, wait_for_ready=True, metadata=(("clicent_key", "client_value"),)) # metadata 给服务器传输消息 grpc.Compression.Gzip:压缩数据
print(response.result)
headers = call.trailing_metadata() # 接受服务器传输过来的消息
print(headers)
print(headers[0].key, headers[0].value)
# print(help(client.HelloYoyo.with_call))
except Exception as e:
print(dir(e)) # 查看对像内所有属于及方法
print(e.code(), e.code().name, e.code().value)
print(e.details())
# response = client.TsetClientRectStream(pb2.TsetClientRectStreamRequest(data='yoyo'))
# for item in response:
# print(item.result)
# response = client.TsetClientSendStream(test())
# print(response.result)
# response = client.TsetTowWayStream(test(), timeout=10) # 请求超时时长
# for request in response:
# print(request.result)
if __name__ == "__main__":
run()