gRPC -- 在 Protobuf 中将 .png 图像从 Java 客户端发送到 Python 服务器

Posted

技术标签:

【中文标题】gRPC -- 在 Protobuf 中将 .png 图像从 Java 客户端发送到 Python 服务器【英文标题】:gRPC -- Send .png image from Java client to Python server in Protobuf 【发布时间】:2016-08-31 00:06:41 【问题描述】:

我正在尝试使用 gRPC 和 ProtoBuf 将图像从 Java 客户端发送到 Python 服务器。我将图像编码为 ByteString 并使用 blockingStub 发送。 Python 服务器接收 ProtoBuf,但 Java ByteString 现在是 Python str。我不确定如何从 str 中恢复图像。

当我调用服务器时:

request.ParseFromString(request.png_encoded)  # Throws error

它引发了:

Traceback(最近一次调用最后一次):

文件“/usr/local/lib/python2.7/dist-packages/grpc/_server.py”,第 364 行,在 _call_behavior 中

返回行为(参数,上下文),真

文件“process_server.py”,第 57 行,在进程中 request.ParseFromString(request.png_encoded)

文件“/usr/local/lib/python2.7/dist-packages/google/protobuf/message.py”,第 185 行,在 ParseFromString self.MergeFromString(序列化)

文件“/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py”,第 1082 行,在 MergeFromString if self._InternalParse(serialized, 0, length) != length:

文件“/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py”,第 1108 行,InternalParse new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)

文件“/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py”,第 850 行,在 SkipField 中 return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)

文件“/usr/local/lib/python2.7/dist-packages/google/protobuf/internal/decoder.py”,第 820 行,在 _RaiseInvalidWireType

raise _DecodeError('Tag has invalid wire type.')

DecodeError:标签的线类型无效。

Java 客户端:

public void run_process(String imPath) 
    logger.info("Will try to retrieve boxes with image " + imPath + " ...");
    File path = new File(imPath);
    byte[] imageInByte = null;
    ByteString byteIm = null;
    try 
        BufferedImage bufferedIm = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bufferedIm = ImageIO.read(path);
        ImageIO.write(bufferedIm, "png", out);
        out.flush();
        imageInByte = out.toByteArray();
        out.close();
        ByteBuffer buf = ByteBuffer.wrap(imageInByte);
        byteIm = ByteString.copyFrom(buf);
     catch (IOException e) 
        e.printStackTrace();
    

    private final ManagedChannel channel;
    channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build();
    private final ProcessServiceGrpc.ProcessServiceBlockingStub blockingStub;
    blockingStub = ProcessServiceGrpc.newBlockingStub(channel);

    ProcessRequest request = ProcessRequest.newBuilder().setPngEncoded(byteIm).build();
    ProcessResponse response;
    try 
        response = blockingStub.process(request);
     catch (StatusRuntimeException e) 
        logger.log(Level.WARNING, "RPC failed: 0", e.getStatus());
        return;
    
    logger.info("Boxes retrieved: " + response.toString());

Python 服务器:

def Process(self, request, context):
    print(type(request.png_encoded))  # prints <type 'str'>
    request.ParseFromString(request.png_encoded)  # Throws error

    # Return empty response for now
    process_response = inference_pb2.ProcessResponse()
    return process_response

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    inference_pb2.add_ProcessServiceServicer_to_server(
        ProcessServiceServicer(), server)
    print "Starting Process Server"
    server.add_insecure_port('localhost:50051')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    serve()

我尝试在 Google 上搜索“Decode Java Protobuf in Python”和“decode java protobuf Bytestring in python”,但没有成功。提前致谢!

【问题讨论】:

【参考方案1】:

ByteString 在 Java 中只是一个不可变的byte[]。 Python 2 等价物是str。它是一个二进制表示。如果您想将图像保存到磁盘,您可以:

with open('out.png', 'wb') as file:
    file.write(request.png_encoded)

【讨论】:

以上是关于gRPC -- 在 Protobuf 中将 .png 图像从 Java 客户端发送到 Python 服务器的主要内容,如果未能解决你的问题,请参考以下文章

protobuf及grpc的client请求

通过 gRPC/Protobuf 进行通信

使用 protobuf-net.Grpc 的客户端回调

如何在 gRPC 响应中打印所有 protobuf 字段,即使是空的

构建 grpc protobuf 耗时太长

思考gRPC :为什么是protobuf