#include<iostream> #include <fstream> #include<string> #include<cstring> #include <algorithm> using namespace std;//非遂爻辞 string h="0123456789abcdef";//16进制 string HexAdd(string pri,string now){//实现字符串的16进制循环加法 int cf=0;//进位标识符 for(int i=3;i>=0;--i){//从低位开始 int ph,nh;//设置pri和now第i位分别对应于h的标号,可以通过标号之和取模16作为标号,从h里找到对应符号,实现加法 for(int j=0;j<16;++j){//pri开找 if(pri[i]==h[j]){ph=j;break;} } for(int j=0;j<h.length();++j){//now开找 if(now[i]==h[j]){nh=j;break;} } int pnch=ph+nh+cf;//标号求和 cf=0;//重置cf if(pnch>=16)cf=1;//若产生进位,cf置1 pri[i]=h[pnch%16];//取模获得对应符号 } if(cf!=0)pri=HexAdd(pri,"0001");//最高位有进位,通过递归保证循环加法 return pri;//返回结果 } int main(){ string fname;//打开的文件名 //路径有: //.\\testfile\\icmp.txt //.\\testfile\\udp.txt //.\\testfile\\tcp.txt string temp;//获取文件内容于temp字符串 cout<<"请输入想要打开的文件:"<<endl;//静态提示路径 cout<<".\\testfile\\icmp.txt"<<endl; cout<<".\\testfile\\udp.txt"<<endl; cout<<".\\testfile\\tcp.txt"<<endl; cin>>fname; fstream fs(fname);//打开文件 if(fs.is_open()){//判断是否成功打开 fs>>temp; cout<<"原始内容为:"<<temp<<endl;//输出原始内容 //接下来进行网际校验,因为都是ip数据报,本算法仅计算ip首部校验,至于icmp、udp、tcp的算法相同,取的数据部分不同罢了,下面是算法步骤: //取ip首部,每两个字节为一组,每组循环加法,和取反 //需要注意的是,发送方的校验位先置为0x0000,算出后再赋值;接收方不用,直接算,若最终结果为0x0000,则接收,否则丢弃 //这算法具体实现,结合实际,就当咱是接收方好了 string pri="0000";//记录累加信息,初始为零 for(int i=28;i<68;i+=4){//测试文件是通过wireshark导出后加工而成的数据,其前14个字节记录着源mac、目的mac和ip协议版本,并不是ip首部,所以跳过 string now=temp.substr(i,4);//每两个字节为单位 pri=HexAdd(pri,now);//开加 cout<<"pri "<<i<<" = "<<pri<<endl;//输出每次加后的结果,做到流程清晰 } for(int i=3;i>=0;--i){//结果取反 int cpn;//pri每位反值的序号 for(int j=0;j<h.length();++j)if(pri[i]==h[j]){cpn=h.length()-1-j;break;}//找到反值序号 pri[i]=h[cpn];//将pri每位取反 } cout<<"接收方的ip首部检验和结果为:0x"<<pri<<endl; fs.close();//关闭文件流 }else cout<<"文件打开失败!";cout<<endl; return 0; }
标签:string,为例,int,IP,16,pri,检验,include,cout From: https://www.cnblogs.com/vusblog/p/16990355.html