前言
基于winpcap和C提示:以下是本篇文章正文内容,下面案例可供参考
一、初步思想
首先需要定义数据帧的格式,这里为了简便设为:
目的MAC(6字节)+源MAC(6字节)+类型(2字节)+数据+CRC32(4字节)
为了发送和接受数据帧,设置两个结构体,一个用来发送数据帧(给底层的),一个用来保存数据帧(给上层或用户的)
还需要设置两个结构体之间的转换函数(封装和解封)
二、结构体设计
1.上层
上层按照数据帧的字段设计即可
text就是要发送的数据,为了节约空间设置成一个字符指针,在使用时分配空间
设置两个CRC32,一个用于保存计算的CRC32,一个用来接收数据帧中的CRC32,用来判断数据在传输过程是否发生改变
typedef struct ether_header{
u_int8_t dhost[6];
u_int8_t shost[6];
unsigned short type;
}ETHHEADER,*PETHHEADER;
typedef struct ether{
ETHHEADER header;
char *text;
int textsize;
u_int32_t CRC32,CRC32_Recv;
}ETHER,*PETHER;
2.底层
就是把上层(用户)的结构体按字节保存到一个字符串中,size是总共要发送的数据字节大小,data也是在使用中分配,这里保存的CRC32用于用户输出、查看
发送的时候调用winpcap中的函数发送
typedef struct frame{
char *data;
int size;
u_int32_t CRC32;
}FRAME,*PFRAME;
三、初始化函数
用于用户设置数据头
ETHHEADER creat_ethheader(char *dhost,char *shost,u_int16_t type){
ETHHEADER ethhdr;
for(int i=0;i<6;i++){
ethhdr.dhost[i]=dhost[i];
ethhdr.shost[i]=shost[i];
}
ethhdr.type=type;
return ethhdr;
}
四、上层和顶层之间的转换函数
实现CRC32计算的代码
u_int32_t crc32_table[256];
void generate_crc32_table()
{
int i, j;
u_int32_t crc;
for (i = 0; i < 256; i++)
{
crc = i;
for (j = 0; j < 8; j++)
{
if (crc & 1)
crc = (crc >> 1) ^ 0xEDB88320;
else
crc >>= 1;
}
crc32_table[i] = crc;
}
}
u_int32_t calculate_crc(u_int8_t *buffer, int len){
generate_crc32_table();
int i;
u_int32_t crc;
crc = 0xffffffff;
for (i = 0; i < len; i++)
{
crc = (crc >> 8) ^ crc32_table[(crc & 0xFF) ^ buffer[i]];
}
crc ^= 0xffffffff;
return crc;
}
封装数据
(上层转换为下层(两个函数作用一样,只是参数不一样))
要点:要判断数据字段是否在46和1500字节之间,还有传过来字符串不要直接使用(可能会越界访问)
FRAME* ether_pack(PETHHEADER pethheader,char *matadata,int size){
PFRAME pf=(PFRAME)malloc(sizeof(FRAME));
char data[1600];
int i;
for(i=0;i<size;i++) data[i]=matadata[i];
if(size<46){
for(;i<45;i++) data[i]=0;
data[45]=46-size;
size=46;
}else if(size>1500){
printf("数据部分过长,大于1500B,失败");
return NULL;
}
pf->size=size+18; //6+6+2+4=18
pf->data=(char *)malloc(pf->size);
for(i=0;i<(pf->size)-4;i++){
if(i<6) pf->data[i]=pethheader->dhost[i];
if(i>=6&&i<12) pf->data[i]=pethheader->shost[i];
if(i>=12&&i<14) pf->data[i]=(pethheader->type)>>((13-i)*8);
if(i>=14) pf->data[i]=data[i-14];
}
u_int32_t crc32=calculate_crc(pf->data,(pf->size)-4);
pf->CRC32=crc32;
for(;i<pf->size;i++){
pf->data[i]=crc32>>(pf->size-1-i)*8;
}
return pf;
}
FRAME* ether_pack_one(PETHER pether){
return ether_pack(&(pether->header),pether->text,pether->textsize);
}
解封数据(下层到上层)
这里没有进行CRC32的比较
PETHER ether_unpack(PFRAME pf){
PETHER pe=(PETHER)malloc(sizeof(ETHER));
int i;
for(i=0;i<6;i++){
pe->header.dhost[i]=pf->data[i];
}
for(;i<12;i++){
pe->header.shost[i]=pf->data[i];
}
pe->textsize=pf->size-18;
pe->text=(char *)malloc(pe->textsize);
for(;i<12+pe->textsize;i++){
pe->text[i-12]=pf->data[i];
}
pe->CRC32_Recv=0;
for(;i<pf->size;i++){
pe->CRC32_Recv=pe->CRC32_Recv|pf->data[i];
if(i!=pf->size-1) pe->CRC32_Recv=pe->CRC32_Recv<<8;
}
u_int32_t crc=calculate_crc(pf->data,pf->size-4);
pe->CRC32=crc;
return pe;
}