【发布时间】:2013-08-26 17:08:40
【问题描述】:
我有一个数据通道,可以通过它传输一些数据,该通道是我自己实现的无线系统,由于物理限制,可靠性较低90%和非常low bandwidth。
为了克服这个问题,我打算用一个应该使用一些数据正确方法的系统来包装整个数据通道,并在数据损坏时发送重新发送请求(将使用校验和检查损坏) .
每当其中一个包装器接收到错误数据时,它都会发送resend request,并在堆栈中为未知数据保留内存中的位置。当可靠性下降时,堆栈将快速增长,因为每一方都会启动互相发送resend request,因为它还没有收到最后一个resend request。即使可靠性恢复正常,它也会尝试重新发送所有resend requests,直到堆栈变空。
这会影响带宽,因为大部分请求不会是数据,而是resend requests。此外,该系统将在 RAM 非常有限的微控制器上运行,只有几个字节,这可能会导致堆栈溢出罕见的情况。
有什么建议吗?
这是一个描述数据通道的Java 模型:
public interface DataChannel {
abstract void send(String s);
abstract void setOnDataListener(OnDataListener l);
interface OnDataListener {
abstract void onData(String s);
}
}
这是一个 DataChannel 的抽象类,用于简化稍后的实现
public abstract class AbstractReliableChannel implements DataChannel,OnDataListener {
protected DataChannel mUnReliable;
private OnDataListener mUnDataListener;
public AbstractReliableChannel(DataChannel unReliableChannel){
mUnReliable = unReliableChannel;
}
@Override
public abstract void send(String s);
@Override
final public void setOnDataListener(OnDataListener l) {
mUnDataListener = l;
}
/*
* Should be called by the implimanting class
*/
final protected void notifiyListenerThatDataReceived(String s){
mUnDataListener.onData(s);
}
/**
* should be called by the implanting class
*/
final protected void sendOverUnreliableChannel(String s){
mUnReliable.send(s);
}
}
这是 UnReliable 频道的实现
public class UnReliableChannel extends AbstractReliableChannel {
public ReliableChannel(DataChannel unReliableChannel) {
super(unReliableChannel);
}
@Override
public void send(String s) {
if( new Random().nextInt(10) % 5 == 0 )
s = ModifyStringRandomly(s);
sendOverUnreliableChannel(s);
}
@Override
public void onData(String s) {
if( new Random().nextInt(10) % 5 == 0 )
s = ModifyStringRandomly(s);
notifiyListenerThatDataReceived(s);
}
}
这是一个可靠的通道实现,我之前描述过
public class ReliableChannel extends AbstractReliableChannel implements Runnable {
public static String DATA = "D";
public static String RESEND = "R";
public static String OK = "O";
private Thread mThread;
public ReliableChannel(DataChannel unReliableChannel) {
super(unReliableChannel);
mThread = new Thread(this);
mThread.start();
}
private Stack<String> mSend;
@Override
public void send(String s) {
mSend.add(s);
}
@Override
public void onData(String s) {
if(isDataValid(s)){
if(s.equals(RESEND)){
String toResend = mSend.pop();
mSend.push(toResend);
mThread.notify();
} else if (s.equals(OK) ) {
mSend.pop();
mThread.notify();
} else if(s.startsWith(DATA)){
notifiyListenerThatDataReceived(s.substring(1));
mSend.push(OK);
}
} else {
mSend.add(RESEND);
mThread.notify();
}
}
private void sendOverUnreliableChannelWithCheckSum(String s){
// ADD checkSUM
sendOverUnreliableChannel(RESEND);
}
@Override
public void run() {
while(true){
while(mSend.isEmpty())
;
sendOverUnreliableChannelWithCheckSum(mSend.pop());
mThread.wait();
}
}
private boolean isDataValid(String s){
// SHOULD BE SOME CHECKSUM IMPLEMINTATION
return true;
}
}
【问题讨论】:
-
有趣。本质上类似于基于 IP 的 TCP,但基于 Java 和通用目的。我也有同样的需求。
-
这是一个独立的项目,它与网络无关,这里的java代码只是为了说明问题。代码本身是在arduino上运行的,实际比特率在附近30 bps,可靠性为 10%。它必须传递一些基本的数据和控制消息,效果很差,我不得不重新实现通道。
标签: java data-transfer reliability