1.编写proto文件:data.proto

syntax = "proto3";
//package example;


service FormatData {   //定义服务,用在rpc传输中
  rpc DoFormat(actionrequest) returns (actionresponse){}
}
message actionrequest {
  string text = 1;
}
message actionresponse{
  string text=1;
}

2.运行

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./data.proto

生成文件:data_pb2_grpc.py 和data_pb2.py

3.编写客户端代码:server.py

# 实现了 server 端用于接收客户端发送的数据,并对数据进行大写处理后返回给客户端

# ! /usr/bin/env python
# -*- coding: utf-8 -*-
# import grpc
# import time
# from concurrent import futures
# import data_pb2, data_pb2_grpc
#
# _ONE_DAY_IN_SECONDS = 60 * 60 * 24
# #localhost
# _HOST = 'localhost'
#
# # _HOST = '192.168.2.107'
# _PORT = '8080'
#
# # 实现一个派生类,重写rpc中的接口函数.自动生成的grpc文件中比proto中的服务名称多了一个Servicer
# class FormatData(data_pb2_grpc.FormatDataServicer):
#     # 重写接口函数.输入和输出都是proto中定义的Data类型
#     def DoFormat(self, request, context):
#         str = request.text
#         print(data_pb2.actionresponse(text=str.upper()))
#         img = base64.b64decode(str)
#         return data_pb2.actionresponse(text=str.upper())  # 返回一个类实例
#
#
# def serve():
#     # 定义服务器并设置最大连接数,corcurrent.futures是一个并发库,类似于线程池的概念
#     grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=4))   # 创建一个服务器
#     data_pb2_grpc.add_FormatDataServicer_to_server(FormatData(), grpcServer)  # 在服务器中添加派生的接口服务(自己实现了处理函数)
#     grpcServer.add_insecure_port(_HOST + ':' + _PORT)    # 添加监听端口
#     grpcServer.start()    #  启动服务器
#     try:
#         while True:
#             print('start===============>')
#             time.sleep(_ONE_DAY_IN_SECONDS)
#     except KeyboardInterrupt:
#         grpcServer.stop(0) # 关闭服务器

import grpc
import time
from concurrent import futures
import data_pb2, data_pb2_grpc
import cv2
import base64
import numpy as np
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
#localhost
_HOST = 'localhost'

# _HOST = '192.168.2.107'
_PORT = '8080'

# 实现一个派生类,重写rpc中的接口函数.自动生成的grpc文件中比proto中的服务名称多了一个Servicer
class FormatData(data_pb2_grpc.FormatDataServicer):
    # 重写接口函数.输入和输出都是proto中定义的Data类型
    def DoFormat(self, request, context):
        str = request.text
        print(data_pb2.actionresponse(text=str.upper()))
        decode_img = base64.b64decode(str)
        img = np.fromstring(decode_img,dtype=np.int8)
        img = np.reshape(img,(480,640,3))
        # img2 = cv2.imdecode(img)
        # cv2.imshow('opencv',img2)

        # img = np.ndarray(img,np.int8)
        cv2.imshow('img',img)
        cv2.waitKey(100)
        return data_pb2.actionresponse(text='xgs')  # 返回一个类实例


def serve():
    # 定义服务器并设置最大连接数,corcurrent.futures是一个并发库,类似于线程池的概念
    grpcServer = grpc.server(futures.ThreadPoolExecutor(max_workers=4))   # 创建一个服务器
    data_pb2_grpc.add_FormatDataServicer_to_server(FormatData(), grpcServer)  # 在服务器中添加派生的接口服务(自己实现了处理函数)
    grpcServer.add_insecure_port(_HOST + ':' + _PORT)    # 添加监听端口
    grpcServer.start()    #  启动服务器
    try:
        while True:
            print('start===============>')
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        grpcServer.stop(0) # 关闭服务器


if __name__ == '__main__':
    serve()

4.编写客户点代码:client.py

# -*- coding: utf-8 -*-
#================================================================
# Copyright (C) 2020 * Ltd. All rights reserved.
# Time : 2020/3/27 22:08
# Author : Xuguosheng

# File : client.py
# Software: PyCharm
# Description :
#================================================================
# 实现了客户端用于发送数据并打印接收到 server 端处理后的数据

# ! /usr/bin/env python
# -*- coding: utf-8 -*-
# import grpc
# import data_pb2, data_pb2_grpc
#
# _HOST = 'localhost'
# _PORT = '8080'
# # class FormatData(data_pb2_grpc.FormatDataServicer):
# #     # 重写接口函数.输入和输出都是proto中定义的Data类型
# #     def DoFormat(self, request, context):
# #         str = request.text
# #         return data_pb2.actionresponse(text=str.upper())  # 返回一个类实例
#
# def run():
#     conn = grpc.insecure_channel(_HOST + ':' + _PORT)  # 监听频道
#     print(conn)
#     client = data_pb2_grpc.FormatDataStub(channel=conn)   # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
#     print(client)
#     for i in range(5):
#
#         response = client.DoFormat(data_pb2.actionrequest(text='hello,world!'))   # 返回的结果就是proto中定义的类
#         print("received: " + response.text)
#
#
# if __name__ == '__main__':
#     run()
import grpc
import data_pb2, data_pb2_grpc
import cv2
import base64
import numpy as np

_HOST = 'localhost'
_PORT = '8080'
# class FormatData(data_pb2_grpc.FormatDataServicer):
#     # 重写接口函数.输入和输出都是proto中定义的Data类型
#     def DoFormat(self, request, context):
#         str = request.text
#         return data_pb2.actionresponse(text=str.upper())  # 返回一个类实例

def run():
    conn = grpc.insecure_channel(_HOST + ':' + _PORT)  # 监听频道
    print(conn)
    client = data_pb2_grpc.FormatDataStub(channel=conn)   # 客户端使用Stub类发送请求,参数为频道,为了绑定链接
    print(client)
    cap = cv2.VideoCapture(0)
    while True:
        ret,frame = cap.read()
        print(frame.shape)

        cv2.waitKey(100)
        # frame_string = frame.tostring()

        # str = cv2.imencode('.jpg',frame)[1]
        str = base64.b64encode(frame)
        # img = base64.b64decode(str)
        # print(type(img))
        # with open("tr2image.png", 'wb') as str2image:
        #     str2image.write(str.decode('base64'))
        # str = frame.tostring()
        cv2.imshow('oo',frame)
        response = client.DoFormat(data_pb2.actionrequest(text=str))   # 返回的结果就是proto中定义的类
        print("received: " + response.text)


if __name__ == '__main__':
    run()

5.运行便可以从客户端传图到服务端