java RXTX 串行连接 - 阻塞 read() 的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5219450/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:02:23  来源:igfitidea点击:

RXTX serial connection - issue with blocking read()

javaserial-portrxtx

提问by Svante

I am trying to use the RXTX library for blocking serial communication on Windows (XP and 7). I have tested the connection with Hyperterminal in both ends, and it works flawlessly.

我正在尝试使用 RXTX 库来阻止 Windows(XP 和 7)上的串行通信。我已经测试了两端与超级终端的连接,它工作得很好。

I set up the connection with the following code: (exception handling and defensive checks omitted for clarity)

我使用以下代码建立了连接:(为清楚起见,省略了异常处理和防御检查)

private InputStream inStream;
private OutputStream outStream;
private BufferedReader inReader;
private PrintWriter outWriter;
private SerialPort serialPort;
private final String serialPortName;

public StreamComSerial(String serialPortName) {
this.serialPortName = serialPortName;
CommPortIdentifier portIdentifier;
portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
CommPort commPort = null;
commPort = portIdentifier.open(this.getClass().getName(),500);
serialPort = (SerialPort) commPort;    serialPort.setSerialPortParams(4800,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
inStream = serialPort.getInputStream();
outStream = serialPort.getOutputStream();
inReader = new BufferedReader(new InputStreamReader(inStream, Settings.getCharset()));
outWriter = new PrintWriter(new OutputStreamWriter(outStream, Settings.getCharset()));

When I use

当我使用

outWriter.println("test message");
flush();

the message is recieved fine on the other end, but calling

另一端收到的消息很好,但调用

inReader.readLine()

imidiately returns "java.io.IOException: Underlying input stream returned zero bytes".

直接返回“java.io.IOException:底层输入流返回零字节”。

I then decided to try and implement my own blocking read logic and wrote this:

然后我决定尝试实现我自己的阻塞读取逻辑并写了这个:

public String readLine() throws IOException {        
    String line = new String();
    byte[] nextByte = {-1};
    while (true) {
        nextByte[0] = (byte)inStream.read();
        logger.debug("int read: " + nextByte[0]);
        if (nextByte[0] == (byte)-1) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            continue;
        }
        logger.debug("byte read: " + nextByte[0]);

        line = line + new String(nextByte);
        if (nextByte[0] == (byte)13) {  // 13 is carriage return in ASCII
            return line;
        }
    }
}

But this code goes in an infinite loop and "nextByte[0] = (byte)inStream.read();" assigns -1 no matter what is sent over the serial connection. In addition, the other end stutters quite badly and only lets me send a character every 1-3 sec. and hangs for a long time if I try to send many characters in a short burst.

但是这段代码进入了一个无限循环和“nextByte[0] = (byte)inStream.read();” 无论通过串行连接发送什么,都分配 -1。另外,另一端卡顿得很厉害,每1-3秒只能让我发送一个字符。如果我尝试在短时间内发送许多字符,则会挂起很长时间。

Any help very appreciated.

非常感谢任何帮助。

*edit - using inStream.read(nextByte) instead of "nextByte[0] = (byte)inStream.read();" does not write to the nextByte variable, no matter what I send to it through the serial connection.

*编辑 - 使用 inStream.read(nextByte) 而不是“nextByte[0] = (byte)inStream.read();” 不写入 nextByte 变量,无论我通过串行连接发送给它什么。

*edit2 - as my code works flawlessly with the SUN javax.comm lib and a win32com.dll I got from a friend, I have ceased trying to make it work with RXTX. I am not interested in unblocking communication, which seems to be the only way other people can make RXTX work.

*edit2 - 因为我的代码与 SUN javax.comm lib 和我从朋友那里得到的 win32com.dll 完美配合,我已经停止尝试让它与 RXTX 一起工作。我对解锁通信不感兴趣,这似乎是其他人可以让 RXTX 工作的唯一方法。

回答by DYA

Use RXTX-2.2pre2, previous versions have had a bug which prevented blocking I/O from working correctly.

使用 RXTX-2.2pre2,以前的版本有一个错误,阻止 I/O 正常工作。

And do not forget to set port to blocking mode:

并且不要忘记将端口设置为阻塞模式:

serialPort.disableReceiveTimeout();
serialPort.enableReceiveThreshold(1);

回答by greydet

I think the code you wrote in your own readLine implementation is buggy. nextByte[0] is never restored to -1 after the first character is read. You should try to use the value returned by inStream.read(nextByte) to state the number of bytes read from the stream instead of the value of your byte array.

我认为您在自己的 readLine 实现中编写的代码有问题。在读取第一个字符后,nextByte[0] 永远不会恢复为 -1。您应该尝试使用 inStream.read(nextByte) 返回的值来说明从流中读取的字节数,而不是字节数组的值。

Anyway I think you should go for an event based method of reading the inputs with a SerialPortEventListener:

无论如何,我认为您应该使用基于事件的方法来使用 SerialPortEventListener 读取输入:

serialPort.addEventListener(new SerialPortEventListener() {

      public void serialEvent(SerialPortEvent evt) {
           switch (evt.getEventType()) {
           case SerialPortEvent.DATA_AVAILABLE:
               dataReceived();
               break;
           default:
               break;
           }
      }
});
serialPort.notifyOnDataAvailable(true);

回答by arnaud

it may not be blocking but when the stream is empty, just catch the IOE and keep reading from it. This is what I do with RXTX-2.1-7 and it works fine, I use it to read and write to an arduino:

它可能不会阻塞,但是当流为空时,只需捕获 IOE 并继续读取它。这就是我用 RXTX-2.1-7 所做的,它工作正常,我用它来读写 arduino:

public static class SerialReader implements Runnable {
    InputStream in;
    public SerialReader(InputStream in) {
        this.in = in;
    }
    public void run() {
        Boolean keepRunning = true;
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String line;
        while (keepRunning) {
            try {
                while ((line = br.readLine()) != null) {
                  //DO YOUR STUFF HERE
                }
            } catch (IOException e) {
                try {
                    //ignore it, the stream is temporarily empty,RXTX's just whining
                    Thread.sleep(200);
                } catch (InterruptedException ex) {
                    // something interrupted our sleep, exit ...
                    keepRunning = false;
                }
            }
        }
    }
}

回答by xwalter

I have solved this way

我已经解决了这种方式

try 
        {
            if(input.ready()==true)
            {
            String inputLine=input.readLine();
            System.out.println(inputLine);
            }

        } catch (Exception e)