2

我相信我知道范围,但我不知道何时何地使用它们或如何使用它们。我无法“获得”范围。考虑这个例子:


假设我们有一个我们无法控制的网络处理程序,只要有一些新数据给我们,它就会在某个线程中调用我们的回调函数:

void receivedData(ubyte[] data)

此数据流包含具有布局的数据包

{
    ushort size;
    ubyte[size] body;
}

但是,网络处理程序并不知道这一点,因此调用dataReceived()可能包含一个或两个部分数据包、一个或几个完整数据包或组合。为简单起见,我们假设没有损坏的数据包,并且data.length == 0在连接关闭时我们会收到一个。

我们现在想要的是一些漂亮的 D 代码,将所有这些混乱变成适当的调用

void receivedPacket(ubyte[] body)

我当然可以想到实现这一目标的“蛮力”方法。但这也许是我的困惑所在:范围可以在其中发挥作用吗?我们可以总结receivedData()成一个不错的范围吗?如何?或者这不是您使用范围的那种问题?为什么不?

(如果使用范围更有意义,请随意重新定义示例。)

4

1 回答 1

2

我要做的是

ubyte[1024] buffer=void;//temp buffer set the size as needed...
ushort filledPart;//length of the part of the buffer containing partial packet
union{ushort nextPacketLength=0;ubyte[2] packetLengtharr;}//length of the next packet

void receivedData(ubyte[] data){
    if(!data.length)return;

    if(nextPacketLength){
        dataPart = min(nextPacketLength-filledPart.length,data.length);

        buffer[filledPart..nextPacketLength] = data[0..dataPart];
        filledPart += dataPart;

        if(filledPart == nextPacketLength){
            receivedPacket(buffer[0..nextPacketLength]);//the call
            filledPart=nextPacketLength=0;//reset state
            receivedData(datadataPart..$]);//recurse
        }
    } else{
        packetLengtharr[]=data[0..2];//read length of next packet

        if(nextPacketLength<data.length){//full paket in data -> avoid unnecessary copies
             receivedPacket(data[2..2+nextPacketLength]);
             receivedData(data[2+nextPacketLength..$]);//recurse
        }else
            receivedData(data[2..$]);//recurse to use the copy code above
    }
}

它是递归的,有 3 种可能的路径:

  1. data为空 -> 无操作

  2. nextPacketLength设置为一个值!= 0 -> 将尽可能多的数据复制到缓冲区中,如果数据包完成,则调用回调并重置filledPartnextPacketLength递归其余的data

  3. nextPacketLength ==0 如果完整的数据包可用调用回调,则读取数据包长度(此处使用联合),然后使用其余数据递归

当数据只包含长度的第一个字节时,只有一个错误仍然存​​在,但我会让你弄清楚(我现在懒得做)

于 2012-11-21T12:49:50.453 回答