zfec是一种前向纠删码,用于给原始数据增加冗余信息,以提高数据的安全性。zfec提供了诸如c、python等语言的接口。在这里只介绍有关c语言的接口。(这篇文章主要是参考学习博客http://www.dullgull.com/2012/07/zfec-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90/,但是代码部分是原创的并且保证是正确的)
zfec源代码的下载地址为:http://pypi.python.org/pypi/zfec
1、fec_t :这是一个结构,通过fec_new() 返回可以得到,不用自己初始化。fec->k 是数据块的数目,fec->n 是所有块总数(数据块+校验块)
2、fec_new():初始化,生成fec_t 结构,并给定了k,m(需要重建数据块数,总数据块数)
3、fec_free():释放初始化的空间
4、fec_encode():编码 (具体参数如下)
5、fec_decode():解码 (具体参数如下)
1、fec_t结构:
1: typedef struct {
2: unsigned long magic;
3: unsigned short k, n; /* parameters of the code */
4: gf* enc_matrix; //其中的k是数据块的个数,n是所有块的总数(包括数据块和校验块)
5: } fec_t;
2、fec_new()
1: fec_t* fec_new(
2: unsigned short k, /*原数据块个数,对应编码理论中k */
3: unsigned short m /*编码后所有数据块个数,对应编码理论中n */
4: )
3、fec_free()
1: void fec_free(
2: fec_t* p
3: )
4、fec_encode()
1: void fec_encode(
2: const fec_t* code, /*fec_t 结构的指针*/
3: const gf*restrict const*restrict const src, /*原始数据指针*/
4: gf*restrict const*restrict const fecs, /*fec 生成的校验数据的指针*/
5: const unsigned*restrict const block_nums,
6: /*记录冗余数据块在整个数据(包含原始数据)中的索引数组*/
7: size_t num_block_nums, /*冗余数组的大小*/
8: size_t sz /*每个数据块的大小*/
9: )
src[0] 到src[ECC_K-1] 是指向第0 个到第ECC_K-1 个数据块的指针;(分别指向D1-D5)
fecs[0] 到fecs[ECC_C-1] 是指向第0 个到第ECC_C-1 个校验块的指针;(需要预先分配好校验块的空间,分别指向C1-C3)
blocks_nums 是校验块索引数组的指针,blocks_nums 指向的空间也应该提前分配好,是一个ECC_C 大小的空间,保存从ECC_K,…,ECC_N-1。(对应下图,索引数组保存5、6、7 )
num_block_nums 是上面blocks_nums 指向空间的大小,也就是校验块个数:ECC_C = ECC_N – ECC_K。
5、fec_decode()
1: void fec_decode(
2: const fec_t* code, /*fec_t 结构的指针*/
3: const gf*restrict const*restrict const inpkts,
4: /*用来恢复丢失数据的数据数组,其内的指针必须按编码前的顺序升序存放,如果丢包则拿冗余块补入,
5: 其中冗余块必须放在丢失数据块的位置。指针所指数组大小为k*/
6: gf*restrict const*restrict const outpkts,
7: /*存放找回的数据块,所指数组大小为丢失块数量*/
8: const unsigned*restrict const index,
9: /*传入的数据包的序号,数组大小为k,对应inpkts中每个数据块在全部数据块中的索引*/
10: size_t sz
11: )
inpkts 是恢复数据块和校验块指针,需要注意的是数据块应该按照其原来的位置放置,缺少数据块的部分用校验块填充,不可以按照数据块校验块顺序放置,否则会解码错误
outpkts 是恢复出来的数据块的指针,也要预先分配空间
index 是用于恢复的数据块与校验块对应在inpkts 里面的索引。
如下图D1/D4/C2 块发生损坏,那么重建的数据块由D2/D3/D5/C1/C3。那么inpkts 指针应该有这样关系:
inpkts->C1(校验块的位置只需和后面index 索引对齐即可)
inpkts+1->D2 (数据块应该保持其原来位置)
inpkts+2->D3(数据块应该保持其原来位置)
inpkts+3->C3(校验块的位置只需和后面index 索引对齐即可)
inpkts+4->D5(数据块应该保持其原来位置)
那么对应index 指向的数组应该为[5,1,2,7,4] ,对应的也就是C1/D2/D3/C3/D5 在初始位置的索引。
写自己的代码的时候需要把源码中的fec.c文件编译成fec.o编译方法如下:gcc -c fec.c -std=c99 然后再和自己写的程序一起进行编译连接。比如你写的程序是test.c ,则这个时候编译成可执行的文件test的方法是:gcc test.c fec.o -o test -std=c99这样就生成了可执行的文件test了。
以下是自己写的一段简单的encode和decode的代码,主要是对指定的字符串进行编码和解码:
#include
#include
#include "fec.h"
#define ECC_K 4
#define ECC_N 8
#define ECC_C (ECC_N-ECC_K)
#define BLK_SZ (24/ECC_K)
int main(int argv,char *argc[])
{
fec_t *code;
char *src[ECC_K];//用来存放数据块的数据
char *fecs[ECC_C];//校验数据的指针
char cdata[25]={0};
unsigned blocks[ECC_C];//用来存放校验块在整个数据中的索引
int i=0;
char data[]="abcdefetefetasetfgerder!";
int index[ECC_K]={4,5,6,7};
char *in_recovery[ECC_K];
char *out_recovery[ECC_K];
char buf_recovery[ECC_K*BLK_SZ+1];//
code=fec_new(ECC_K,ECC_N);
for(i=0;i {//初始化数据块数据
src[i]=data+BLK_SZ*i;//这里是存储的是六个数据节点中的数据,就是相当于把data的数据分散到了六个数据节点上面。然后src【i】各存一个数据节点中的数据
}
for(i=0;i {//初始化校验块
blocks[i]=ECC_K+i;
fecs[i]=cdata+i*BLK_SZ;
}
printf("the src is %s\n",*src);
printf("the cdata is:%s\n",cdata);
printf("the src is: %s\n",*fecs);
for(i=0;i {//这是整数
printf("the blocks is:%d\n",blocks[i]);
}
fec_encode(code,src,fecs,blocks,ECC_C,BLK_SZ);
printf("the encode is end!\n");
printf("the src is %s\n",*src);
for(i=0;i {//这种情况就是在四个数据块都出现错误的时候的进行的恢复
in_recovery[i]=fecs[i];
out_recovery[i]=buf_recovery+i*BLK_SZ;
}
fec_decode(code,in_recovery,out_recovery,index,BLK_SZ);
buf_recovery[ECC_K*BLK_SZ]='\0';
printf("Recovery is :%s\n",buf_recovery);
//注意这里的buf_recovery的内容是出现错误的数据块的数据,在这里是D1、D2、D3、D4的数据
//以下验证的是D1、D4、C1、C2四个块出错然后进行恢复的代码
printf("the second deconde!\n");
/* index[0]=6;
index[1]=1;
index[2]=2;
index[3]=7;
memset(buf_recovery,0,sizeof(buf_recovery));
in_recovery[0] = fecs[2];
in_recovery[1] = data+1*BLK_SZ;
in_recovery[2] = data+2*BLK_SZ;
in_recovery[3] = fecs[3];
*/
//以下验证的是D2、D3、C1、C2四个块出错然后进行恢复的代码
//其中恢复的结果是恢复出错的块的数据
index[0]=0;
index[1]=6;
index[2]=7;
index[3]=3;
memset(buf_recovery,0,sizeof(buf_recovery));
in_recovery[0] = data+0*BLK_SZ;
in_recovery[1] = fecs[2];
in_recovery[2] = fecs[3];
in_recovery[3] = data+3*BLK_SZ;
for(i = 0 ; i < ECC_K ; i++)
{//其中buf_recovery中存放的是出现错误的数据块的数据,在这里是D2、D3的数据
out_recovery[i] = buf_recovery + i*BLK_SZ;
}
fec_decode(code, in_recovery, out_recovery, index, BLK_SZ);
buf_recovery[ECC_K*BLK_SZ] = '\0';
printf("Recovery is :%s\n",buf_recovery);
//printf("the k=%d and n=%d ",code->k,code->n);
return 0;
}