日期:2014-05-19  浏览次数:20674 次

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函数来接收串口的数据,这样可以保证我能收到主机任何时候发送过来的数据。
接收数据的子线程代码:
Java code

/**
     * 该线程用来接收串口收到的信息
     */
    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可自行设计与规定。。。