Java RXTX中的接收问题

Java RXTX中的接收问题,java,serial-port,rxtx,Java,Serial Port,Rxtx,我已经使用RXTX大约一年了,没有太多问题。我刚刚启动了一个新的程序来与一个新的硬件进行交互,所以我重新使用了我在其他项目中使用的connect()方法,但我遇到了一个以前从未见过的奇怪问题 问题 该设备工作正常,因为当我连接超级终端时,我发送和接收我期望的东西,并且(SPM)反映了这一点 然而,当我运行我编写的简单超级终端克隆来诊断我的主应用程序存在的问题时,根据SPM,字节被发送,但什么也没有收到,我的SerialPortEventListener从未启动。即使我检查主循环中的可用数据,re

我已经使用RXTX大约一年了,没有太多问题。我刚刚启动了一个新的程序来与一个新的硬件进行交互,所以我重新使用了我在其他项目中使用的connect()方法,但我遇到了一个以前从未见过的奇怪问题

问题

该设备工作正常,因为当我连接超级终端时,我发送和接收我期望的东西,并且(SPM)反映了这一点

然而,当我运行我编写的简单超级终端克隆来诊断我的主应用程序存在的问题时,根据SPM,字节被发送,但什么也没有收到,我的SerialPortEventListener从未启动。即使我检查主循环中的可用数据,
reader.ready()
也会返回
false
。如果忽略此检查,则会出现异常,详细信息如下

connect()方法的相关部分

// Configure and open port
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
                                      .open(owner,1000)
port.setSerialPortParams(baud, databits, stopbits, parity);
port.setFlowControlMode(fc_mode);
final BufferedReader br = new BufferedReader(
                            new InputStreamReader(
                              port.getInputStream(), 
                              "US-ASCII"));

// Add listener to print received characters to screen
port.addEventListener(new SerialPortEventListener(){
  public void serialEvent(SerialPortEvent ev) {
    try {
      System.out.println("Received: "+br.readLine());
    } catch (IOException e) { e.printStackTrace(); }
  }   
});
port.notifyOnDataAvailable();
例外情况

java.io.IOException: Underlying input stream returned zero bytes
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
        at java.io.InputStreamReader.read(InputStreamReader.java:167)
        at java.io.BufferedReader.fill(BufferedReader.java:136)
        at java.io.BufferedReader.read(BufferedReader.java:157)
        at <my code>
(可能太简单了,但不妨从某个地方开始……)

这个端口正在使用吗?而不是:

port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
                                      .open(owner,1000)
那么:

CommPortIdentifier portIdentifier;
try {
    portIdentifier = CommPortIdentifier.getPortIdentifier(name);
} catch (NoSuchPortException nspe) {
    // handle?
}
if (portIdentifier.isCurrentlyOwned()) {
    // handle?
}
port = portIdentifier.open(owner, 1000);
if (!(port instanceof SerialPort)) {
    // handle?
}

您是否接受了任何异常?

几个月前我尝试了RXTX,但遇到了类似的问题。我建议两件事:

  • 使用com0com创建虚拟组件。启用跟踪日志记录。比较使用超级终端和运行自己的程序时的日志。这种差异会突出你做错了什么

  • 在我看来,RXTX的设计是有缺陷的,它的实现也是有缺陷的(看看它的源代码,真是一团糟!)。我在上发布了一个替代库,但有以下警告:它仅限于Windows,没有预构建的二进制文件。这两种情况在不久的将来都会发生变化。如果你有兴趣尝试它给我发一封电子邮件使用,我会给你一个预建版本


  • 好的,对不起,我花了这么长时间才回到这个问题上来。这是我如何让事情运转起来的

    注意:此方法不适用于所有人,请在复制/粘贴到您自己的代码之前阅读以下内容

    public void connect(CommPortIdentifier portId) throws Failure {
        if (portId == null)
            throw new Failure("No port set");
    
        try { port = (SerialPort) portId.open(getClass().getName(), 10000); } 
        catch (PortInUseException e) {
            throw new Failure("Port in use by " + e.currentOwner,e); }
    
        try {
            port.setSerialPortParams(9600, SerialPort.DATABITS_8,
                    SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
            port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN
                                  | SerialPort.FLOWCONTROL_RTSCTS_OUT);
        } catch (UnsupportedCommOperationException e) { throw new Failure(e); }
    
        port.setRTS(true);
    
        // More setup
    }
    
    所以,在我的例子中,问题是我的特定设备需要RTS流控制。其他设备可能需要不同的东西(CTS、XON/XOFF),因此请查看该设备的手册。默认情况下,RXTX禁用所有流控制机制(与HyperTM或其他程序不同)。启用每一项都是一个分两步的过程

  • 拥有SerialPort对象后,调用
    setFlowControlMode()
    方法,并按位或(“
    |
    ”)调用必要的
    SerialPort.FLOWCONTROL
    常量
  • 将适当的流控制设置为true或false(就像我使用
    port.setRTS(true)
  • 对于其他有类似问题的人,如果这不起作用,我建议

  • 使用和/或(两个窗口)等串行端口监控程序查看实际情况
  • 向RXTX开发人员发送电子邮件rxtx@qbang.org(他们很有帮助)

  • 这个问题有一个更简单的解决办法。这就是我所做的:

    BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String line;
    
        while (keepRunning) {
            try {
                while ((br.ready()) && (line = br.readLine()) != null) {
    ....
    }
    

    如果在阅读之前检查缓冲区是否“准备就绪”,应该没有问题。

    好的,我确实意识到这个线程非常旧,但这些解决方案都不适合我。我也有同样的问题,我尝试了所有的方法来解决它,但没有成功。然后我研究了问题的原因,当不处理串行通信时,它发生在文件的末尾。因此,我想我需要为Java应用程序接收到的任何内容添加一个结尾,特别是一个换行符(\n)。果然,它解决了我的问题!希望这对新手有所帮助,因为我不希望这对已经在这个线程中的任何人都有帮助…

    如果有人仍然得到
    java.io.IOException:在您使用RXTX的br.readline()读取字符后,底层输入流返回零字节(即使您首先检查br.readline()==null),只需使用try/catch执行此简单修复:

    字符串行;
    虽然(正确){
    试一试{
    line=br.readLine();
    }捕获(IOE异常){
    System.out.println(“不再接收字符”);
    打破
    }
    //将行打印为只读
    如果(line.length()!=0)
    系统输出打印项次(行);
    }
    
    我做了一些搜索,似乎这是解决这个问题的最好/最简单的方法


    编辑:我收回这句话。我试过了,结果还是有些问题。我建议直接使用原始InputStream,并使用InputStream.read()实现您自己的读取/读取行方法。这对我很有用。

    谢谢,但是connect()方法的其余部分会捕获所有这些异常,并打印堆栈跟踪和死亡。@我看到了如何在serialport对象上设置flowcontrol。这是清楚的。然而,我试图弄清楚您是如何检测到已发送的流控制字符的?我和你一样使用XON XOFF vs RTS。但我认为应该是类似的。0x13,0x11是我希望在触发的serialEvent中看到的字符吗?您是如何在代码中检测到这一点的?@ril3y我不记得曾经见过流控制字符。在串口监视器或PortMon(回答中的链接)中,我看到窗口右下角有一组红色和绿色的圆圈,其中一个是CTS,另一个是XON/XOFF。当一切正常时,它们是绿色的。否则,它们是红色的。哦,非常感谢详细的解决方案。我花了整整两天的时间调试这个,但现在终于有了一个解决方案。现在也有了。
    BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String line;
    
        while (keepRunning) {
            try {
                while ((br.ready()) && (line = br.readLine()) != null) {
    ....
    }