将数据分段为数据包的算法

时间:2015-08-04 16:27:27

标签: algorithm networking bin-packing

让我们说我想将一些数据单元分段为数据包(每个数据包的最大大小可以说是1024字节)。每个数据单元可以是可变大小的,例如:

a = 20 bytes
b = 1000 bytes
c = 10 bytes
d = 800 bytes

任何人都可以建议任何有效的算法来创建具有这种随机数据的数据包有效利用带宽?我不能将各个数据单元拆分成字节......它们整个数据包都在一个数据包内。

编辑:数据单元的排序无关紧要!

2 个答案:

答案 0 :(得分:0)

根据您的要求以及您希望花费多少时间,有几种不同的方式。正如@amit在评论中提到的一般问题是NP-Hard。但是,您可以通过一些简单的更改来获得一些改进。

在我们去那里之前,你确定你真的需要这样做吗?大多数网络层都有一个数据包大小(或更大)的缓冲区。当您写入网络时,它会将您的数据放入该缓冲区。如果您没有完全填充缓冲区,代码将在发送前暂时延迟。如果在该延迟期间添加更多数据,则新数据将添加到缓冲区。缓冲区在填充后或延迟超时到期后发送。

因此,如果你有一个循环,一次写一个字节到网络,那就不像你将创建大量的单字节数据包。

在接收方,最低级别的网络层接收整个数据包,但不能保证您接收数据的呼叫将获得整个数据包。也就是说,发送方可能会发送一个800字节的数据包,但在接收端,第一次读取调用可能只返回50或273个字节。

当然,这取决于您正在读取数据的级别。如果您正在谈论Java或.NET之类的东西,那么您的网络堆栈接口是通过套接字的,那么您几乎肯定无法保证对socket.Read()的调用将返回整个数据包。

现在,如果可以保证每次调用read都返回一个完整的数据包,那么最简单的方法是将所有内容序列化为一个大缓冲区,然后将其发送到多个1,024 - 数据包。你需要在第一个数据包的前面创建一个标题,说明将发送多少总字节数,这样接收者就知道会发生什么。结果将是一堆1,024字节的数据包,可能后面跟一个稍小的最终数据包。

如果要确保数据对象完全包含在单个数据包中,则必须执行以下操作:

add a to buffer
if remaining buffer < size of b
    send buffer
    clear buffer
add b to buffer
if remaining buffer < size of c
    send buffer     
    clear buffer
add c to buffer
... etc ...

答案 1 :(得分:0)

这是一些简单的JavaScript伪代码。数据包将保持有序,并且将以最佳方式使用带宽。

packets = [];

PACKET_SIZE = 1024;
currentPacket = [];

function write(data) {
  var len = currentPacket.length + data.length;
  if(len < PACKET_SIZE) {
    currentPacket = currentPacket.concat(data);
  } else if(len === PACKET_SIZE) {
    packets.push(currentPacket.concat(data));
    currentPacket = [];
  } else { // if(len > PACKET_SIZE) {
    packets.push(currentPacket);
    currentPacket = data;
  }
}
function flush() {
  if(currentPacket.length > 0) {
    packets.push(currentPacket);
    currentPacket = [];
  }
}

write(data20bytes);
write(data1000bytes);
write(data10bytes);
write(data800bytes);
flush();

编辑由于您拥有所有数据块,并且您希望最佳地将它们无序打包(bin pack),因此您可以尝试每个块的排列以获得准确答案或与之妥协最佳猜测/第一拟合类型算法。