gpt4 book ai didi

java - JSSC - 断开连接会导致串行端口阻塞

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:57 24 4
gpt4 key购买 nike

我正在使用 JSSC 串行端口包在我的应用程序和连接到串行端口的设备之间交换数据。我制作了一个简单的应用程序,可以将识别消息发送到设备并打印响应。我希望它能够抵抗连接错误(例如在通信过程中拔掉电缆后)。

操作顺序 Init -> Open -> IDN -> Close 工作得很好。当我打开端口后拔下电缆时,我无法发送消息(对我来说似乎合乎逻辑)并关闭端口(没有什么可以关闭的,所以我也理解这一点)。

一开始,我很惊讶再次插入电缆后无法关闭端口,但我发现每次连接设备后,操作系统都会给它一个不同的编号,JSSC 库使用该编号来处理端口。幸运的是,事实证明,只需在重新连接后打开端口就可以解决所有问题,因为应用程序可以再次发送消息。

不幸的是,当端口打开时多次尝试断开/连接电缆时,就会出现问题。每次尝试后,应用程序的运行速度都会越来越慢,最终会达到无法再发送消息的状态。另一件事是,在这种状态下,所有串行端口(不仅仅是我尝试与之通信的串行端口)都被阻止,我什至无法通过类似终端的应用程序访问它们。

所以问题是:

如何使应用程序能够抵抗连接中断而不阻塞端口和损失性能?

我想这可能与某种资源、内存管理等有关,但我对这些东西的了解不足以自己解决问题。

沟通的实现:

import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;

class Connection implements SerialPortEventListener {
private static final int SERIAL_PORT_BAUD_RATE = 9600;
private static final int SERIAL_PORT_DATA_BITS_NUMBER = 8;
private static final int SERIAL_PORT_STOP_BITS_NUMBER = 1;
private static final int SERIAL_PORT_PARITY = 0;

private SerialPort serialPort;
private String portName;

public Connection(String portName) {
this.portName = portName;
}

public void open() throws SerialPortException {
serialPort = new SerialPort(portName);
serialPort.openPort();
serialPort.setParams(SERIAL_PORT_BAUD_RATE,
SERIAL_PORT_DATA_BITS_NUMBER,
SERIAL_PORT_STOP_BITS_NUMBER,
SERIAL_PORT_PARITY);
serialPort.addEventListener(this);
}

public void close() throws SerialPortException {
if (serialPort != null) {
serialPort.closePort();
}
}

public void simpleMessage() throws SerialPortException {
if (serialPort != null) {
serialPort.writeString("IDN");
}
}

@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
if (serialPortEvent.getEventType() == SerialPortEvent.RXCHAR) {
try {
System.out.println(serialPort.readString());
} catch (SerialPortException e) {
System.out.println("Error while reading a string.");
}
}
}
}

主类:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.io.IOException;

public class MainApplication extends Application{
public static void main(String [] args) {
Application.launch();
}

@Override
public void start(Stage primaryStage) throws Exception {
Pane rootPane = null;
FXMLLoader loader = new FXMLLoader();
loader.setLocation(MainApplication.class.getResource("front.fxml"));

try{
rootPane = loader.load();
} catch (IOException exception) {
exception.printStackTrace();
}

Scene scene = new Scene(rootPane);
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(event -> {
Platform.exit();
System.exit(0);
});
}
}

FXML 代码:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.VBox?>

<StackPane fx:id="rootPane"
xmlns="http://javafx.com/javafx/8.0.60"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="FrontController">
<VBox>
<Button text="Init" onAction="#init"/>
<Button text="Open" onAction="#openPort"/>
<Button text="Close" onAction="#closePort"/>
<Button text="IDN" onAction="#idn"/>
<Button text="Get Ports" onAction="#getPorts"/>
<Button text="Is opened?" onAction="#isPortOpen"/>
</VBox>
</StackPane>

Controller :

import javafx.fxml.FXML;
import jssc.SerialPortException;
import jssc.SerialPortList;
import java.util.Arrays;

public class FrontController {

private Connection connection;

@FXML
private void init() {
String portName = "COM4";
connection = new Connection(portName);
}

@FXML
private void openPort() {
try {
connection.open();
} catch (SerialPortException e) {
e.printStackTrace();
}
}

@FXML
private void closePort() {
try {
connection.close();
} catch (SerialPortException e) {
e.printStackTrace();
}
}

@FXML
private void idn() {
try {
connection.idnMessage();
} catch (SerialPortException e) {
e.printStackTrace();
}
}

@FXML
private void getPorts() {
System.out.println(Arrays.toString(SerialPortList.getPortNames()));
}

@FXML
private void isPortOpen() {
System.out.println(connection.getSerialPort().isOpened());
}
}

最佳答案

基本上,有时在不关闭的情况下拔出设备(实际上在 Windows 操作系统中大多数情况下)会使操作系统处于不一致的状态。移除设备后,您需要进行清理。请注意,即使设备已被移除,关闭端口也非常重要。我们可以保留 close 的返回值。这向操作系统暗示应用程序对设备也不感兴趣,因此操作系统可以自由释放我们也想要的资源。因此,简而言之,我们需要创建一个线程来监视我们的设备是否连接到系统。

关于java - JSSC - 断开连接会导致串行端口阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44369151/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com