【问题标题】:RXTX serial connection - issue with blocking read()RXTX 串行连接 - 阻塞 read() 问题
【发布时间】:2011-07-10 07:40:03
【问题描述】:

我正在尝试使用 RXTX 库来阻止 Windows(XP 和 7)上的串行通信。我已经在两端测试了与 Hyperterminal 的连接,并且可以正常工作。

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

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 秒发送一个字符。如果我尝试在短时间内发送许多字符,则会挂起很长时间。

非常感谢任何帮助。

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

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

【问题讨论】:

  • *edit - 进一步调试表明无论通过串行连接发送什么,inStream.read(nextByte) 都不会写入 nextByte 变量。
  • @Peter Knego - 是的,它看起来相关,但我对他试图实现的多线程解锁行为不感兴趣。
  • 嗨 Svante。我也在为同样的问题苦苦挣扎。你在哪里得到 win32com.dll 和 javax.comm。你能指导我吗。

标签: java serial-port rxtx


【解决方案1】:

我认为您在自己的 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);

【讨论】:

  • 感谢您的建议。我尝试将 RXTX 换成 SUN(或 Oracle)javax.comm 包和朋友发送的 win32com.dll。我的代码现在可以完美运行。所以我会坚持下去。太糟糕了,我听说过关于 TXRX 的好消息,但是当他们的 InputStream 实现不支持阻塞行为的承诺时,我就没有什么可以用了。
  • 我认为问题不是来自 RXTX 本身,而是更具体到您的配置。无论如何,如果 javax.comm 在跨平台使用和部署方面满足您的需求,那就太好了!
  • 嗨 Svante。我也在为同样的问题苦苦挣扎。你在哪里得到 win32com.dll 和 javax.comm。你能指导我吗。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 在其中设置错误计数器是否明智?例如,如果您连续三、十或一百次获得相同的IOException,那您不应该忽略它吗?否则,当您遇到合法错误时,您可能会陷入尴尬的循环。
    【解决方案4】:

    我已经这样解决了

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 2013-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多