Java进程“管道已结束”问题

发布于 2024-08-23 19:39:46 字数 2425 浏览 6 评论 0原文

我正在使用 Java Process API 编写一个类,该类从网络接收二进制输入(例如通过 TCP 端口 A),对其进行处理并将二进制输出写入网络(例如通过 TCP 端口 B)。我使用的是Windows XP。代码如下所示。有两个函数,分别为 run()receive():run 在开始时调用一次,而 receive 在通过网络接收到新输入时调用。 Run 和 receive 是从不同的线程调用的。

run进程启动一个exe并接收exe的输入和输出流。 Run 还会启动一个新线程,将 exe 的输出写入端口 B。receive

    public void run() {
        try {
            Process prc = // some exe is `start`ed using ProcessBuilder
                    OutputStream procStdIn = new BufferedOutputStream(prc.getOutputStream());
            InputStream procStdOut = new BufferedInputStream(prc.getInputStream());
                    Thread t = new Thread(new ProcStdOutputToPort(procStdOut));
                    t.start();

                    prc.waitFor();
                    t.join();
                    procStdIn.close();
                    procStdOut.close();
        } catch (Exception e) {
            e.printStackTrace();
            printError("Error : " + e.getMessage());
        }
    }

将接收到的输入从端口 A 转发到 exe。

    public void receive(byte[] b) throws Exception {
        procStdIn.write(b);
    }

    class ProcStdOutputToPort implements Runnable {
        private BufferedInputStream bis;
        public ProcStdOutputToPort(BufferedInputStream bis) {
            this.bis = bis;
        }
        public void run() {
            try {
                int bytesRead;
                int bufLen = 1024;
                byte[] buffer = new byte[bufLen];
                while ((bytesRead = bis.read(buffer)) != -1) {
                    // write output to the network
                }
            } catch (IOException ex) {
                Logger.getLogger().log(Level.SEVERE, null, ex);
            }
        }
    }

问题是我在 receive() 中得到以下堆栈,并且 prc.waitfor() 随后立即返回。行号显示堆栈在写入 exe 时。

 The pipe has been ended
 java.io.IOException: The pipe has been ended
 at java.io.FileOutputStream.writeBytes(Native Method)
 at java.io.FileOutputStream.write(FileOutputStream.java:260)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
 at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
 at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
 at xxx.receive(xxx.java:86)

任何有关此的建议将不胜感激。

I am using Java Process API to write a class that receives binary input from the network (say via TCP port A), processes it and writes binary output to the network (say via TCP port B). I am using Windows XP. The code looks like this. There are two functions called run() and receive(): run is called once at the start, while receive is called whenever there is a new input received via the network. Run and receive are called from different threads.

The run process starts an exe and receives the input and output stream of the exe. Run also starts a new thread to write output from the exe on to the port B.

    public void run() {
        try {
            Process prc = // some exe is `start`ed using ProcessBuilder
                    OutputStream procStdIn = new BufferedOutputStream(prc.getOutputStream());
            InputStream procStdOut = new BufferedInputStream(prc.getInputStream());
                    Thread t = new Thread(new ProcStdOutputToPort(procStdOut));
                    t.start();

                    prc.waitFor();
                    t.join();
                    procStdIn.close();
                    procStdOut.close();
        } catch (Exception e) {
            e.printStackTrace();
            printError("Error : " + e.getMessage());
        }
    }

The receive forwards the received input from the port A to the exe.

    public void receive(byte[] b) throws Exception {
        procStdIn.write(b);
    }

    class ProcStdOutputToPort implements Runnable {
        private BufferedInputStream bis;
        public ProcStdOutputToPort(BufferedInputStream bis) {
            this.bis = bis;
        }
        public void run() {
            try {
                int bytesRead;
                int bufLen = 1024;
                byte[] buffer = new byte[bufLen];
                while ((bytesRead = bis.read(buffer)) != -1) {
                    // write output to the network
                }
            } catch (IOException ex) {
                Logger.getLogger().log(Level.SEVERE, null, ex);
            }
        }
    }

The problem is that I am getting the following stack inside receive() and the prc.waitfor() returns immediately afterwards. The line number shows that the stack is while writing to the exe.

 The pipe has been ended
 java.io.IOException: The pipe has been ended
 at java.io.FileOutputStream.writeBytes(Native Method)
 at java.io.FileOutputStream.write(FileOutputStream.java:260)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:105)
 at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
 at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
 at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
 at xxx.receive(xxx.java:86)

Any advice about this will be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毁我热情 2024-08-30 19:39:46

这意味着您在另一端已经关闭管道后才向管道写入数据。

这表明您的应用程序协议中存在重大错误。

This means you are writing to the pipe after the other end has already closed it.

That indicates a major error in your application protocol.

酒中人 2024-08-30 19:39:46

我最近遇到了同样的问题,并且找到了解决方案。

首先,“管道已结束”错误不是Java错误——它来自Windows系统。根据 MSDN:

使用进程已关闭管道,或者,如果您正在尝试写入
对于管道,没有可用的读取器。

信息不是很丰富。但是,如果进程本身关闭了管道,则可能意味着进程中发生了一些错误

要检查这一点,请将来自进程的错误重定向到文件:

File f = new File("errors.txt");
pb.redirectError(f);

在我的例子中(我一直在尝试执行 SrcML 解析器)文件包含以下内容:

.\libs\srcML-Win\src2srcml.exe: unrecognised option `--language Java'
Try 'src2srcml --help' for more information.

修复此问题解决了问题。

I have had the same problem recently and I have found a solution.

First of all, "The pipe has been ended" error is not a Java error - it comes from Windows system. According to MSDN:

The using process has closed the pipe or, if you are trying to write
to the pipe, there are no available readers.

Not very informative. However, if process has closed the pipe itself, it may mean that some errors occurred in process.

To check this, redirect errors coming from process, for instance, to a file:

File f = new File("errors.txt");
pb.redirectError(f);

In my case (I've been trying to execute SrcML parser) file contained this:

.\libs\srcML-Win\src2srcml.exe: unrecognised option `--language Java'
Try 'src2srcml --help' for more information.

Fixing this solved the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文