一、python服务端配置
1、添加依赖
pip install grpcio
pip install protobuf
pip install grpcio_tools
2、编辑协议文件ocrapi.proto
syntax = "proto3"; //说明使用proto3语法定义协议
package com.qlisv.grpc.ocr; // 包名,注意与所在文件夹保持一致
service Ocrapi {
// 用于识别单色图片上的文字,不包含表情的图片
rpc getText (ImgRequest) returns (ImgResponse) {}
// 用于识别复杂的彩色图片上的文字
rpc getImgText (ImgRequest) returns (ImgResponse) {}
}
message ImgRequest {
// 文件地址
string imgPath = 1;
}
message ImgResponse {
// 识别到的文本内容
string content = 1;
}
3、进入协议文件所在目录下执行命令
python -m grpc_tools.protoc -I ./ --python_out=. --grpc_python_out=. ocrapi.proto
执行成功后会在协议文件同目录下新生成以下两个文件:
ocrapi_pb2.py 里面有消息序列化类
ocrapi_pb2_grpc.py 包含了服务器 Service 类和客户端 Stub 类,以及待实现的服务 RPC 接口。
文件目录如下:
4、编写服务端脚本ocr_server.py
import grpc
# from concurrent import futures
# from cnstd import CnStd
# from cnocr import CnOcr
# import random
import com.qlisv.grpc.ocr.ocrapi_pb2 as ocrapi_pb2, com.qlisv.grpc.ocr.ocrapi_pb2_grpc as ocrapi_pb2_grpc
class OcrapiServicer(ocrapi_pb2_grpc.OcrapiServicer):
def getText(self, request, ctx):
_res = 'msg from server.getText'
return ocrapi_pb2.ImgResponse(content=_res)
def getImgText(self, request, context):
_res = 'msg from server.getImgText'
return ocrapi_pb2.ImgResponse(content=_res)
def main():
# 服务端
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
# 实例化
servicer = OcrapiServicer()
# 注册本地服务
ocrapi_pb2_grpc.add_OcrapiServicer_to_server(servicer, server)
# 监听端口
server.add_insecure_port('127.0.0.1:19999')
# 开始接收请求进行服务
server.start()
# 使用 ctrl+c 可以退出服务
try:
print("running...")
server.wait_for_termination()
except KeyboardInterrupt:
print("stopping...")
server.stop(0)
if __name__ == '__main__':
main()
二、Java客户端配置
1、ocrapi.proto文件配置
使用与python相同的proto文件,放在proto文件夹下,包名和路径也保持一致
2、在maven中加入以下grpc依赖库
<!--grpc-->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.29.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.29.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.29.0</version>
</dependency>
3、在maven的build标签下加入以下插件
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<!--grpc plugin-->
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.30.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
4、maven运行clean、package
运行成功后,系统会自动在target\generated-sources\protobuf生成对应的文件目录和文件,文件目录如下:
5、编写java客户端代码
package com.qlisv.grpc.ocr;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* <p> 通过ocr获取图片上的文本 </p>
*
* @author AsyDong
* @version 1.0
* @time 2020/6/23 16:23
*/
public class OcrapiClient {
private static final Logger logger = LoggerFactory.getLogger(OcrapiClient.class);
private ManagedChannel channel;
private String rpcOcrServer = "127.0.0.1:19999";
/**
* Construct client for accessing HelloWorld server using the existing channel.
*/
public OcrapiClient() {
this.channel = getChannel();
}
private OcrapiGrpc.OcrapiBlockingStub getBlockingStub() {
// Passing Channels to code makes code easier to test and makes it easier to reuse Channels.
OcrapiGrpc.OcrapiBlockingStub blockingStub = OcrapiGrpc.newBlockingStub(getChannel());
return blockingStub;
}
private ManagedChannel getChannel() {
if (channel == null || channel.isShutdown() || channel.isTerminated()) {
// Create a communication channel to the server, known as a Channel. Channels are thread-safe
// and reusable. It is common to create channels at the beginning of your application and reuse
// them until the application shuts down.
channel = ManagedChannelBuilder.forTarget(rpcOcrServer)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext()
.build();
}
return channel;
}
private void closeChannel() {
try {
if (channel != null && !channel.isShutdown()) {
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
logger.error("通道关闭异常");
e.printStackTrace();
}
}
/**
* 调用服务端的获取图像上的文本
*
* @param path 图片地址
* @author AsyDong
* @version 1.0
* @time 2020/6/23 16:23
*/
public String getText(String path) {
logger.info(" try to connect server ...");
try {
OcrapiOuterClass.ImgRequest request = OcrapiOuterClass.ImgRequest.newBuilder().setImgPath(path).build();
OcrapiOuterClass.ImgResponse response;
response = getBlockingStub().getText(request);
logger.debug("提取结果: " + response.getContent());
return response.getContent();
} catch (StatusRuntimeException e) {
logger.error("RPC failed: {0}", e.getStatus());
return "";
} finally {
closeChannel();
}
}
/**
* 调用服务端的获取图像上的文本,用于复杂图片背景
*
* @param path 图片地址
* @author AsyDong
* @version 1.0
* @time 2020/6/23 16:23
*/
public String getImgText(String path) {
logger.info(" try to connect server ...");
try {
OcrapiOuterClass.ImgRequest request = OcrapiOuterClass.ImgRequest.newBuilder().setImgPath(path).build();
OcrapiOuterClass.ImgResponse response;
response = getBlockingStub().getImgText(request);
logger.debug("提取结果: " + response.getContent());
return response.getContent();
} catch (StatusRuntimeException e) {
logger.error("RPC failed: {0}", e.getStatus());
return "";
} finally {
closeChannel();
}
}
/**
* Greet server. If provided, the first element of {@code args} is the name to use in the
* greeting. The second argument is the target server.
*/
public static void main(String[] args) throws Exception {
String path = "d:/TMP/t1.png";
OcrapiClient client = new OcrapiClient();
System.out.println(client.getText(path));
System.out.println(client.getImgText(path));
}
}
最后先启动python服务端,然后再启动java客户端就可以啦。