上一篇文章我们说编写ip数据包头部,我们现在来实现从08到最后的编程工作。ps:直接上代码是不是头都大了!先说说重要步骤吧!
1、启动套接字并建立套接字。(注意:在socket参数中我们使用的type是SOCK_RAW)
2、组帧(建立新的函数,用到函数的传址调用,标明组帧信息和长度)
3、发送数据 sendto
4、接受数据 revcfrom
5、设置发送接收超时选项
注意:我们本节主要内容是组帧操作,尤其是校验和的输出。
组帧的方法主要有两种,一种是一个字节一个字节的输出,比如:
buf[0]=0x08;
buf[1]=0;
buf[2]=0;//校验和初始值
buf[3]=0;//校验和初始值
buf[4]=0;
buf[5]=1;
buf[6]=0;
buf[7]=0x31;
for(int i=8;i<len;i++)
{
buf[i]='a'+(i-8);
if(i>=8+23)
buf[i]-=23;
}
这种方法有点老套了 ,我们用另一种方法结构体的方法
typedef struct iphead{
UCHAR utype; //类型
CCHAR ucode; //代码
USHORT us_sum; //校验和
USHORT us_sign; //标识符
USHORT us_in; //序列号
}IPHERD,*PIPHEAD;
void combination_Frame(char buf[],int len)
{
PIPHEAD pih=(PIPHEAD)buf;//char指针强烈转成PIPHEAD类型的指针
pih->utype=0x08;
pih->ucode=0x00;
pih->us_sum=0x00;//校验和初始值
pih->us_sign=0x0100;
pih->us_in=0x3100;
for(int i=8;i<len;i++)
{
buf[i]='a'+(i-8);
if(i>=8+23)
buf[i]-=23;
}
char buf_send[MAX_LEN_SEND];
combination_Frame(buf_send,MAX_LEN_SEND);
重点来了来了!!!!!!
校验和?!
1、将校验和字段置为0。(上一步已经做了)
2、将每两个字节(16位)相加(二进制求和)直到最后得出结果,若出现最后还剩一个字节继续与前面结果相加。
3、(溢出)将高16位与低16位相加,直到高16位为0为止。
4、将最后的结果(二进制)取反。
USHORT cal_sum(char buf[],int len)
{
//将每两个字节(16位)相加(二进制求和)直到最后得出结果,
USHORT *BUF=(USHORT*)buf;
UINT sum=0;
while(len/2>0){
sum+=*BUF;
BUF++;
len-=2;
}
if(len>0)
sum+=*(UCHAR*)BUF;
sum=((sum&0xffff0000)>>16)+(sum&0x0000ffff);
sum=((sum&0xffff0000)>>16)+(sum&0x0000ffff);
//若出现最后还剩一个字节继续与前面结果相加。
return(USHORT)(~sum);
//将最后的结果(二进制)取反
return 0;
}
注意:
1、将buf转成ushort类型的。
2、如果出现奇数的将最后一个字节与前面相加,什么意思呢?举个例子(十进制为例):
57+60=127,超出了两位数,将27与1相加的28,两位数成功。
最后:在函数里面引用校验和就可以了,注意,要在最后引用才可以,因为需要用到组帧的所有数据。
我们来看一下结果吧!!
它成功了!!!(手动鼓掌)
参考链接:link.
peace!!!!未完待续……