我有一个数据通道,可以通过它传输一些数据,该信道是一个由我自己实现的无线系统,由于物理上的限制,它具有低可靠性的90%和非常low bandwidth。
为了克服这一问题,我计划用一个系统包装整个数据通道,该系统应该使用一些数据正确的方法,并在数据损坏时发送重新发送请求(将使用校验和检查损坏)。
每当一个包装器接收到一个坏数据时,它就会发送一个resend request,并在内存中保留未知数据的位置,当可靠性下降时,stack.The堆栈中的resend request将迅速增长,因为双方都将开始发送resend request,因为它还没有收到最后一个resend request。即使可靠性恢复正常,它也会尝试重新发送所有的resend requests,直到堆栈变为空。
这将影响带宽,因为大多数请求都不是数据,但是resend requests.Moreover这个系统将运行在内存非常有限的微控制器上,只有几个字节,这在很少情况下可能会导致堆栈溢出。
有什么建议吗?
下面是一个描述数据通道的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;
}
}发布于 2013-08-25 20:25:00
问题来自于您的低效协议设计,而不是编程。要在有损耗的信道中获得可靠的链接,只需使用tcp连接或定义类似于tcp的协议。基本上,在Tx上对每个数据包进行编号。在Rx,当你收到一个坏的数据包时,就把它扔掉,以节省内存。您可以通过检查是否所有数据包都有连续编号来检查数据包的完整性。通过保持一个适当的滑动窗口,您将达到良好的有效带宽和负担得起的内存使用。
https://stackoverflow.com/questions/18406375
复制相似问题