Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java版本套接字调用 Software caused connection abort: socket write error #106

Open
monawolf opened this issue May 16, 2024 · 2 comments

Comments

@monawolf
Copy link

monawolf commented May 16, 2024

Java版本调用时,Ocr.class#sendJsonToOcr,writer.write(sw.getBuffer().toString());前面添加一段
if (OcrMode.SOCKET_SERVER == mode) {
writer.close();
reader.close();
clientSocket.close();
clientSocket = new Socket(serverAddr, serverPort);
clientSocket.setKeepAlive(true);
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8));
}
长连接第二次调用时会导致 Software caused connection abort: socket write error,所以套接字启动时改为短连接比较好

jerrylususu added a commit to jerrylususu/PaddleOCR-json-java-api that referenced this issue Aug 25, 2024
@jerrylususu
Copy link
Contributor

jerrylususu commented Aug 25, 2024

hi,我是 Java API 的维护者。首先很感谢你的反馈,我目前已经在新版本上根据你的反馈进行了修改。此外,paddleocr-json(本仓库)仅负责 paddleocr-json 本体的开发,各类语言的封装 API 的 issue 需要到各自的仓库反馈(如 https://github.com/jerrylususu/PaddleOCR-json-java-api )。欢迎后续的 issues 和 PR!

@foreach-every
Copy link

java socket 客户端 依赖fastjson2

  <dependency>
      <groupId>com.alibaba.fastjson2</groupId>
      <artifactId>fastjson2</artifactId>
      <version>2.0.43</version>
  </dependency>

package com.jjc.serverwork.work.paddle;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;

import com.alibaba.fastjson2.JSON;

/**
 * PaddleOCR-json java客户端
 * powered by <a href="https://github.com/hiroi-sora/PaddleOCR-json">PaddleOCR-json</a>
 * powered by <a href="https://github.com/jerrylususu/PaddleOCR-json-java-api">PaddleOCR-json-java-api</a>
 * @author lx {@code @datetime} 2024/12/16 19:29
 **/
public interface PaddleOCRJsonClient {

    default OcrResponse runOcrImgBytes(byte[] data) {
        return this.runOcrImgBase64(Base64.getEncoder().encodeToString(data));
    }

    static PaddleOCRJsonClient newSocketOcrClient(String serverAddr, int serverPort) {
        return new SimplePaddleOCRJsonSocketClient(serverAddr, serverPort);
    }

    OcrResponse runOcrImgBase64(String base64);

    /**
     * PaddleOCR-json java Socket客户端
     */
    class SimplePaddleOCRJsonSocketClient implements PaddleOCRJsonClient {

        private static final Duration TRY_LOCK_TIMEOUT = Duration.ofSeconds(30);

        private final String serverAddr;

        private final int serverPort;

        // 相同的ocr服务不能并发访问
        private static final Map<SimplePaddleOCRJsonSocketClient, ReentrantLock> LOCK_MAP = new ConcurrentHashMap<>(10);

        private SimplePaddleOCRJsonSocketClient(String serverAddr, int serverPort) {
            this.serverAddr = serverAddr;
            this.serverPort = serverPort;
        }

        @Override
        public OcrResponse runOcrImgBase64(String base64) {
            Map<String, String> reqJson = new HashMap<>();
            reqJson.put("image_base64", base64);
            try {
                return this.doOcr(reqJson);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        public OcrResponse doOcr(Map<String, String> reqJson) throws TimeoutException, IOException, InterruptedException {
            ReentrantLock lock = LOCK_MAP.computeIfAbsent(this, k -> new ReentrantLock());
            if (!lock.tryLock(TRY_LOCK_TIMEOUT.getSeconds(), TimeUnit.SECONDS)) {
                throw new TimeoutException("get lock timeout");
            }
            try (Socket clientSocket = new Socket(serverAddr, serverPort);
                BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8))) {

                StringWriter sw = new StringWriter();
                sw.write(JSON.toJSONString(reqJson));

                writer.write(sw.getBuffer().toString());
                writer.write("\r\n");
                writer.flush();

                StringBuilder builder = new StringBuilder();
                String resp;
                while ((resp = reader.readLine()) != null) {
                    builder.append(resp);
                }
                return JSON.parseObject(builder.toString()).toJavaObject(OcrResponse.class);
            } finally {
                lock.unlock();
            }
        }

        @Override
        public final boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof SimplePaddleOCRJsonSocketClient that)) {
                return false;
            }
            return serverPort == that.serverPort && Objects.equals(serverAddr, that.serverAddr);
        }

        @Override
        public int hashCode() {
            int result = Objects.hashCode(serverAddr);
            result = 31 * result + serverPort;
            return result;
        }
    }

    class OcrStatusCode {
        public static final int SUCCESS_CODE = 100;

        private static final Map<Integer, String> MAP = new HashMap<>() {
            {
                super.put(100, "识别到文字");
                super.put(101, "未识别到文字");
                super.put(200, "图片路径不存在");
                super.put(201, "图片路径string无法转换到wstring");
                super.put(202, "图片路径存在,但无法打开文件");
                super.put(203, "图片打开成功,但读取到的内容无法被opencv解码");
                super.put(300, "base64字符串解析为string失败");
                super.put(301, "base64字符串解析成功,但读取到的内容无法被opencv解码");
                super.put(400, "json对象 转字符串失败");
                super.put(401, "json字符串 转对象失败");
                super.put(402, "json对象 解析某个键时失败");
                super.put(403, "未发现有效任务");
            }
        };

        public static String getDesc(int code) {
            return MAP.get(code);
        }

        public static boolean isSuccess(int code) {
            return code == SUCCESS_CODE;
        }

    }

    class OcrEntry {
        private String text;

        private int[][] box;

        private BigDecimal score;

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public int[][] getBox() {
            return box;
        }

        public void setBox(int[][] box) {
            this.box = box;
        }

        public BigDecimal getScore() {
            return score;
        }

        public void setScore(BigDecimal score) {
            this.score = score;
        }

        @Override
        public String toString() {
            return "OcrEntry{" +
                "text='" + text + '\'' +
                ", box=" + Arrays.toString(box) +
                ", score=" + score +
                '}';
        }
    }

    class OcrResponse {
        private int code;

        private List<OcrEntry> data;

        private String msg;

        private String hotUpdate;

        public OcrResponse() {}

        public boolean isSuccess() {
            return OcrStatusCode.isSuccess(this.code);
        }

        public boolean isError() {
            return !isSuccess();
        }

        public OcrResponse(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public List<OcrEntry> getData() {
            return data;
        }

        public void setData(List<OcrEntry> data) {
            this.data = data;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public String getHotUpdate() {
            return hotUpdate;
        }

        public void setHotUpdate(String hotUpdate) {
            this.hotUpdate = hotUpdate;
        }

        @Override
        public String toString() {
            return "OcrResponse{" +
                "code=" + code +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                ", hotUpdate='" + hotUpdate + '\'' +
                '}';
        }
    }

}



demo

package com.jjc.serverwork.work.paddle;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import com.jjc.serverwork.work.paddle.PaddleOCRJsonClient.OcrEntry;
import com.jjc.serverwork.work.paddle.PaddleOCRJsonClient.OcrResponse;
import com.jjc.serverwork.work.paddle.PaddleOCRJsonClient.OcrStatusCode;

/**
 * @author lx {@code @datetime} 2024/12/17 11:59
 **/
public class Demo {
    public static void main(String[] args) throws IOException {
        String path = "B:\\TEMP\\paddleOCR-test\\11.png";
        PaddleOCRJsonClient ocrClient = PaddleOCRJsonClient.newSocketOcrClient("192.168.0.11", 3746);
        byte[] bytes = Files.readAllBytes(new File(path).toPath());
        OcrResponse rep = ocrClient.runOcrImgBytes(bytes);

        if (rep.isError()) {
            System.err.println("=======================识别错误 msg:" + rep.getMsg() + ",desc:" + OcrStatusCode.getDesc(rep.getCode())+"======================");
            return;
        }


        System.out.println("=======================识别成功===============================");

        for (OcrEntry datum : rep.getData()) {
            System.out.println(datum.getText());
        }

    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants