Java 相当于套接字连接的SerialPortEvent
我正在编写一个与测量设备连接的应用程序。 此设备可以通过串行和网络连接进行连接。 我使用的串行端捕获通过Java 相当于套接字连接的SerialPortEvent,java,sockets,events,serial-port,Java,Sockets,Events,Serial Port,我正在编写一个与测量设备连接的应用程序。 此设备可以通过串行和网络连接进行连接。 我使用的串行端捕获通过SerialPortEvent发送的数据 现在我正试图用套接字完成同样的事情。我的连接正常,可以从设备发送/接收数据。问题是我强制Thread.sleep等待所有数据准备就绪。但是现在我想自动捕获接收的数据,就像使用SerialPortEvent一样 这是一个由两部分组成的问题: 插座是否存在类似事件?或者在这种情况下,定制解决方案更可取?如果是,请补充说明 如何完成插座的可用数据 下面是Se
SerialPortEvent
发送的数据
现在我正试图用套接字
完成同样的事情。我的连接正常,可以从设备发送/接收数据。问题是我强制Thread.sleep等待所有数据准备就绪。但是现在我想自动捕获接收的数据,就像使用SerialPortEvent
一样
这是一个由两部分组成的问题:
插座是否存在类似事件?或者在这种情况下,定制解决方案更可取?如果是,请补充说明
SerialEventPort
的一段代码(仅是必要的捕获部分),作为我也想用套接字完成的工作的参考:
@Override
public void serialEvent(SerialPortEvent event)
{
if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
try
{
int available = inputStream.available();
byte[] readBuffer = new byte[available];
if (available > 0)
{
inputStream.read(readBuffer);
}
}
}在本节中,声明如下:
我建议使用与选择器和SelectionKey连接的java.nio.channels.SocketChannel。此解决方案在某种程度上是基于事件的,但比普通套接字更复杂
如果您决定采用该解决方案,您将在链接答案中找到代码示例
但是,如果你说的是,不,没有事件。我喜欢回答一个类似的问题:
这通常是通过为客户端生成一个单独的线程来完成的,该线程不断地从流中对read()进行阻塞调用-这样,一旦数据可用,read()调用就会解除阻塞并对其接收到的内容进行操作(“事件激发”),然后返回到阻塞等待下一个事件
根据我的经验,这也是Java中处理套接字的主要方式。我编写了一个基于事件的套接字的实现。由于读取是可阻止的,因此最有可能不需要线程来阻止主程序:
public class ObservableSocket extends Thread {
private final Socket socket;
private final ArrayList<ObservableSocketListener> listeners;
private volatile boolean isReading;
private int BUFFER_SIZE = 1024;
public ObservableSocket(String host, int port) throws UnknownHostException, IOException {
this.socket = new Socket(host, port);
this.listeners = new ArrayList<ObservableSocketListener>(1);
isReading = true;
this.start();
}
public void addListener(ObservableSocketListener l) {
if (!listeners.contains(l)) {
listeners.add(l);
}
}
public void removeListener(ObservableSocketListener l) {
if (!listeners.contains(l)) {
listeners.remove(l);
}
}
public void die() {
isReading = false;
try {
this.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public void write(byte[] data) throws IOException {
socket.getOutputStream().write(data);
socket.getOutputStream().flush();
}
private byte[] getData(byte[] buffer, int red) {
byte[] redData = new byte[red];
System.arraycopy(buffer, 0, redData, 0, red);
return redData;
}
@Override
public void run() {
byte[] buffer = new byte[BUFFER_SIZE];
int red;
ObservableSocketEvent event;
try {
while (isReading && (red = socket.getInputStream().read(buffer)) > -1) {
event = new ObservableSocketEvent(this, getData(buffer, red));
for (ObservableSocketListener l : listeners) {
l.dataAvailable(event);
}
}
}
catch (Exception exception) {
event = new ObservableSocketEvent(this, exception);
for (ObservableSocketListener l : listeners) {
l.errorOccured(event);
}
}
finally {
if (socket != null) {
try {
socket.close();
for (ObservableSocketListener l : listeners) {
l.closed(new ObservableSocketEvent(this));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
以及活动类别:
public class ObservableSocketEvent extends EventObject {
private final byte[] data;
private final Exception exception;
public ObservableSocketEvent(Object source) {
super(source);
this.data = null;
this.exception = null;
}
public ObservableSocketEvent(Object source, byte[] data) {
super(source);
this.data = data;
this.exception = null;
}
public ObservableSocketEvent(Object source, Exception exception) {
super(source);
this.data = null;
this.exception = exception;
}
public byte[] getData() {
return data;
}
public Exception getException() {
return exception;
}
}
我让服务器生成一些随机数据来测试这段代码,这是我在客户端的类main方法中使用它的方式:
ObservableSocket observableSocket = new ObservableSocket("localhost", 3339);
observableSocket.addListener(new ObservableSocketListener() {
@Override
public void dataAvailable(ObservableSocketEvent event) {
System.out.println("data received: "+new String(event.getData()));
}
@Override
public void closed(ObservableSocketEvent event) {
System.out.println("closing socket");
}
@Override
public void errorOccured(ObservableSocketEvent event) {
System.out.println("error occured");
event.getException().printStackTrace();
}
});
Thread.currentThread().sleep(10000);
observableSocket.die();
它输出:
data received: data 0
data received: data 1
data received: data 2
data received: data 3
data received: data 4
closing socket // thread is alive here
BUILD SUCCESSFUL (total time: 10 seconds) // thread dies here
就我的测试而言,需要客户端中的sleep
,因为die
方法:
- 退出读取循环(通过设置为false的标志)
- 并等待线程死亡()
- 实例化
可观察数据包后,
立即连接,并启动 - 您必须从非
线程的线程调用observatesocket
方法(例如,不要从该类中调用该方法)die
- 在本节中,声明如下:
我建议使用与选择器和SelectionKey连接的java.nio.channels.SocketChannel。此解决方案在某种程度上是基于事件的,但比普通套接字更复杂
如果您决定采用该解决方案,您将在链接答案中找到代码示例
但是,如果你说的是,不,没有事件。我喜欢回答一个类似的问题:
这通常是通过为客户端生成一个单独的线程来完成的,该线程不断地从流中对read()进行阻塞调用-这样,一旦数据可用,read()调用就会解除阻塞并对其接收到的内容进行操作(“事件激发”),然后返回到阻塞等待下一个事件
根据我的经验,这也是Java中处理套接字的主要方式。我编写了一个基于事件的套接字的实现。由于读取是可阻止的,因此最有可能不需要线程来阻止主程序:
public class ObservableSocket extends Thread {
private final Socket socket;
private final ArrayList<ObservableSocketListener> listeners;
private volatile boolean isReading;
private int BUFFER_SIZE = 1024;
public ObservableSocket(String host, int port) throws UnknownHostException, IOException {
this.socket = new Socket(host, port);
this.listeners = new ArrayList<ObservableSocketListener>(1);
isReading = true;
this.start();
}
public void addListener(ObservableSocketListener l) {
if (!listeners.contains(l)) {
listeners.add(l);
}
}
public void removeListener(ObservableSocketListener l) {
if (!listeners.contains(l)) {
listeners.remove(l);
}
}
public void die() {
isReading = false;
try {
this.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public void write(byte[] data) throws IOException {
socket.getOutputStream().write(data);
socket.getOutputStream().flush();
}
private byte[] getData(byte[] buffer, int red) {
byte[] redData = new byte[red];
System.arraycopy(buffer, 0, redData, 0, red);
return redData;
}
@Override
public void run() {
byte[] buffer = new byte[BUFFER_SIZE];
int red;
ObservableSocketEvent event;
try {
while (isReading && (red = socket.getInputStream().read(buffer)) > -1) {
event = new ObservableSocketEvent(this, getData(buffer, red));
for (ObservableSocketListener l : listeners) {
l.dataAvailable(event);
}
}
}
catch (Exception exception) {
event = new ObservableSocketEvent(this, exception);
for (ObservableSocketListener l : listeners) {
l.errorOccured(event);
}
}
finally {
if (socket != null) {
try {
socket.close();
for (ObservableSocketListener l : listeners) {
l.closed(new ObservableSocketEvent(this));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
}
以及活动类别:
public class ObservableSocketEvent extends EventObject {
private final byte[] data;
private final Exception exception;
public ObservableSocketEvent(Object source) {
super(source);
this.data = null;
this.exception = null;
}
public ObservableSocketEvent(Object source, byte[] data) {
super(source);
this.data = data;
this.exception = null;
}
public ObservableSocketEvent(Object source, Exception exception) {
super(source);
this.data = null;
this.exception = exception;
}
public byte[] getData() {
return data;
}
public Exception getException() {
return exception;
}
}
我让服务器生成一些随机数据来测试这段代码,这是我在客户端的类main方法中使用它的方式:
ObservableSocket observableSocket = new ObservableSocket("localhost", 3339);
observableSocket.addListener(new ObservableSocketListener() {
@Override
public void dataAvailable(ObservableSocketEvent event) {
System.out.println("data received: "+new String(event.getData()));
}
@Override
public void closed(ObservableSocketEvent event) {
System.out.println("closing socket");
}
@Override
public void errorOccured(ObservableSocketEvent event) {
System.out.println("error occured");
event.getException().printStackTrace();
}
});
Thread.currentThread().sleep(10000);
observableSocket.die();
它输出:
data received: data 0
data received: data 1
data received: data 2
data received: data 3
data received: data 4
closing socket // thread is alive here
BUILD SUCCESSFUL (total time: 10 seconds) // thread dies here
就我的测试而言,需要客户端中的sleep
,因为die
方法:
- 退出读取循环(通过设置为false的标志)
- 并等待线程死亡()
- 实例化
可观察数据包后,
立即连接,并启动 - 您必须从非
线程的线程调用observatesocket
方法(例如,不要从该类中调用该方法)die