在不可靠的链路传送数据 比如udp
如果需要增加数据传输的可靠性
我们可以在传输原始数据的时候 增加冗余数据
这样 只要我们收到了一定数量的数据包(不需要所有的)
就可以还原出原始的数据包
比如原始数据是“10”
分成两个包,分别为“1”和“0”
通过异或计算出一个冗余包“0”
我们收到任意两个就能组装出原始的包(知道次序的情况下)
这有些类似磁盘冗余阵列的原理

这些纠错编码的理论不少
实际上可以直接拿来用的代码很少见
好不容易找到了这个 zfec
C代码 GPL 提供了Python接口
作者看起来是个水果迷
在他的Mac中测试效率不错
FEC是Forward Error Correction的简称,意为前向纠错

虽然给了代码 实际要用起来还是很麻烦的
所以这里记录一下方法


1 fec_t* fec_new(unsigned k, unsigned m);
k 把原始数据包分成k块
m 编码后生成m块数据块
块的大小都是一致的,所以很显然m>k,其中编码后的m块中,前k块就是原始的数据

2 void fec_encode(const fec_t* code, const gf*restrict const*restrict const src, gf*restrict const*restrict const fecs, const unsigned*restrict const block_nums, size_t num_block_nums, size_t sz);
编码,参数比较难看,src是包含原始数据指针的一个数组(原始数据分成k块),fecs 是返回的包含冗余数据指针的数组,block_nums为冗余数组的序号,由我们设置传入的,k<=序号

3 void fec_decode(const fec_t* code, const gf*restrict const*restrict const inpkts, gf*restrict const*restrict const outpkts, const unsigned*restrict const index, size_t sz);
基本同上,我们只需要任意k个包就可以还原。inpkts是将收到的数据包按序传入,如果丢包则拿一个冗余包补入。outpkts是返回我们缺失的数据包,index是我们传入的数据包的序号,sz是每个包的大小

4 void fec_free(fec_t* p);
不过 即使这样,还是有内存泄露,自己改改吧
//
说不清楚 看代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fec_t* p = fec_new( 4,6);
 
char buf[1024] = {0};
for ( int i = 0; i &lt; 1024; i++)
buf[i]= i % 255;
char* src[] = {buf, buf + 256, buf + 512, buf + 768};
 
char dest[512] = {0};
char* const fecs[] = { dest, dest + 256};
 
UINT block_nums[] = {4,5};//原始数据编号是0,1,2,3
UINT num_block_nums = 2; //block_nums的大小
UINT sz = 1024 / 4;
 
fec_encode(p, (const gf*const*)src, (gf*const*const)fecs, block_nums, num_block_nums, sz);
 
// 解码,假设我们丢失了原始的数据包 0,3
 
char* inpkts[] = {fecs[0], buf + 256, buf + 512, fecs[1]};//必须按顺序,丢失的包由冗余包补齐
char output[512] = {0};
char* const outpkts[] = { output, output + 256};
UINT index[] = {4, 1, 2, 5}; //对应inpkts的顺序
 
fec_decode(p, (const gf* const*const)inpkts, (gf* const* const)outpkts, (const unsigned* const)index, sz);
 
if ( 0 == memcmp( src[0], outpkts[0], 256))
TRACE(L"ok");
 
if ( 0 == memcmp( src[3], outpkts[1], 256))
TRACE(L"ok");
 
fec_free(p);

随便看看