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

发布于 2024-10-21 04:34:57 字数 2358 浏览 3 评论 0原文

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

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

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()));

当我使用

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

消息时,另一端收到良好的消息,但

inReader.readLine()

立即调用返回“java.io.IOException:底层输入流返回零字节” ”。

然后我决定尝试实现我自己的阻塞读取逻辑并编写了以下内容:

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;
        }
    }
}

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

非常感谢任何帮助。

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

*edit2 - 由于我的代码可以完美地与 SUN javax.comm lib 和我从朋友那里获得的 win32com.dll 配合使用,因此我已不再尝试使其与 RXTX 配合使用。我对解除通信阻塞不感兴趣,这似乎是其他人可以使 RXTX 工作的唯一方法。

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.

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".

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.

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.

*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.

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

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

发布评论

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

评论(4

¢好甜 2024-10-28 04:34:57

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

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

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

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

And do not forget to set port to blocking mode:

serialPort.disableReceiveTimeout();
serialPort.enableReceiveThreshold(1);
趁年轻赶紧闹 2024-10-28 04:34:57

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

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

serialPort.addEventListener(new SerialPortEventListener() {

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

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.

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

serialPort.addEventListener(new SerialPortEventListener() {

      public void serialEvent(SerialPortEvent evt) {
           switch (evt.getEventType()) {
           case SerialPortEvent.DATA_AVAILABLE:
               dataReceived();
               break;
           default:
               break;
           }
      }
});
serialPort.notifyOnDataAvailable(true);
高速公鹿 2024-10-28 04:34:57

它可能不会阻塞,但当流为空时,只需捕获 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;
                }
            }
        }
    }
}

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:

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;
                }
            }
        }
    }
}
月光色 2024-10-28 04:34:57

我已经这样解决了

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

        } catch (Exception e) 

I have solved this way

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

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