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, /*生成的校驗數據的指針*/
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 在初始位置的索引。
#include<stdio.h>
#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<ECC_K;i++)
{//初始化數據塊數據
src[i]=data+BLK_SZ*i;//這裏是存儲的是六個數據節點中的數據,就是相當於把data的數據分散到了六個數據節點上面。然後src【i】各存一個數據節點中的數據
}
for(i=0;i<ECC_C;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<ECC_C;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<ECC_K;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;
}