当前位置:编程学习 > JAVA >>

java串口通信多线程的数据收发问题

大家好,我现在做一个串口通信的项目,有一个主机和一个从机,通过串口来通信,我这里是从机,主机或从机向对方发送一个请求,这个请求里会带1个ID号,用来标明该请求的序号,接受方收到这个请求后,都需要回应一个ACK响应,ACK里边包含这个请求的ID号,来向发送方标明已经收到这个请求。有以下两种可能:
情况1:从机向主机发送一个请求,并且需要主机回应一些数据。图示如下:

在这种情况下:从机先向主机发送一个ID=1的请求,然后主机向从机回复ACK(id=1),向从机说明收到了这个请求,此时从机需要先等待主机的ACK响应,如果从机没有收到主机的ACK(ID=1),则从机重新向主机发送ID=1的请求,只到收到主机的ACK。然后主机再向从机回应ID=1的请求所需要的数据(ID=2),同理,从机收到数据后也需要向主机回应一个ACK(ID=2).
情况2:主机向从机发送状态改变,但是从机不知道主机什么时候会发这个信息,所以从机需要一直能够接收到主机的信息。
图示如下:


我原先设计的思路是:创建一个子线程,在子线程中使用read函数来接收串口的数据,这样可以保证我能收到主机任何时候发送过来的数据。
接收数据的子线程代码:

/**
 * 该线程用来接收串口收到的信息
 */
private class ReadThread extends Thread {

@Override
public void run() {
super.run();
while(!isInterrupted()) {
int size;
try {
if (mInputStream == null) return;
size = mInputStream.read(serialBuffer);
if (size > 0) {
onDataReceived(new String(serialBuffer, 0, size));
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}

我在主线程中向主机发送请求,但是这样就出现了一个问题,当我在主线程中向主机发送请求时,我需要在主线程中接收主机回应的ACK来判断主机是否收到我这个请求。
接受数据
问题1:此时我是不是需要先interrupted接收线程,在主线程中使用read函数来接收主机的ACK响应?假如是这样,频繁的interrupted和start线程是否会耗费巨大的系统资源。
问题2:如果我在主线程中使用read函数,假设此时物理连接断开了,read函数是不是就阻塞了我的主线程。
所以请求大家帮我考虑下怎么来设计比较合理,谢谢?
--------------------编程问答--------------------
引用
上次做了一个基于电信SMGP接口的短信平台。。。

看了它的实现方式大概如下:

启动服务时:
启动两个线程。。

线程一:监听服务端返回的数据包,其中包括【接收状态报告数据包,接收回复短信数据包,接收链路检查数据包】。
线程一接收到的数据包,根据其状态【等于LZ设计中的包头的ID号】号来判断是什么包,然后作对应处理【代码较多,就不贴出来了】。。

线程二:往客户端发送数据包,其中包括【短消息发送数据包,发送链路检查数据包】

当然这是长连接。。。我看了看LZ的这个图,和SMGP的原理差不多。。。LZ可以为每个相同的ID号的包设计一个状态码,然后根据状态码判断数据包类型。。。

然后回答你的问题:
问题1:此时我是不是需要先interrupted接收线程,在主线程中使用read函数来接收主机的ACK响应?假如是这样,频繁的interrupted和start线程是否会耗费巨大的系统资源。

回答:不需要,直接用子线程接收所有主机返回来的ACK响应,根据ID号及状态码来判断做相应处理。。让主线程和子线程各自负责相应的工作。。不会存在interrupted和start现象

你设计弊端:如果interrupted掉接收线程,用主线程去接收。。。那么你的主线程一会接收一会发送,在并发时,要乱套。。。而且不好管理。。



问题2:如果我在主线程中使用read函数,假设此时物理连接断开了,read函数是不是就阻塞了我的主线程。
所以请求大家帮我考虑下怎么来设计比较合理,

回答:如果按照我上面的思路,子线程就是负责接收的线程,当连接断开时,去自动重新连接。。。还有通过链路包来保持通道正常。。一旦链路包发现通道断开,就自动重新连接。。。

对于链路包的自动连接次数:LZ可自行设计与规定。。。
--------------------编程问答-------------------- LZ好像发了两个相同的帖子 --------------------编程问答-------------------- kouyiSC,你好,看了你的说明,就是这个问题还没搞明白,从机接收到从主机发送回来的ACK(id=1),我怎么通知到发送线程,id=1的请求已经发送成功了? --------------------编程问答-------------------- 你的图中是从机--》主机,然后主机-->从机。。。对吧


启动两个线程。。

线程一:监听服务端返回的数据包,其中包括【接收状态报告数据包,接收回复短信数据包,接收链路检查数据包】。
线程二:往客户端发送数据包,其中包括【短消息发送数据包,发送链路检查数据包】


当从机通过“发送线程”将数据包发到主机。。主机收到信息后,将回送一个数据包回来,这个数据包包含了:你本身的ID=1,还有我说的状态码Status=1【例如:1表示请求数据包发送成功的状态】。

而从机本身还有一个“接收线程【监听发送回来的数据包】”,这两个线程是一直开启的,,并且串口处于长连接状态。。一旦有数据包回来,就可以接收到。。然后通过接收的数据包的ID号和状态码来判断请求已经发送成功【如上:包的Status=1,ID=1表示请求已经发送成功】了。。。。 --------------------编程问答-------------------- 这个状态码。是对你的数据包类型的标记。。。从你的图来看 好像有两种类型的数据包: 请求的数据包,和需要数据的数据包。。。
数据包类型,这些都是你编程之前定义好的。。。 --------------------编程问答-------------------- 嗯,是的,我的是有两种数据包的,我再考虑下这个问题,谢谢!
补充:Java ,  Java相关
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,