tracert 实现伪代码

#include 
#include 
#include 
using namespace std;
#pragma comment(lib, "Ws2_32.lib")

//IP报头
typedef struct
{
    unsigned char hdr_len:4;        //4位头部长度
    unsigned char version:4;        //4位版本号
    unsigned char tos;            //8位服务类型
    unsigned short total_len;        //16位总长度
    unsigned short identifier;        //16位标识符
    unsigned short frag_and_flags;    //3位标志加13位片偏移
    unsigned char ttl;            //8位生存时间
    unsigned char protocol;        //8位上层协议号
    unsigned short checksum;        //16位校验和
    unsigned long sourceIP;        //32位源IP地址
    unsigned long destIP;        //32位目的IP地址
} IP_HEADER;

//ICMP报头
typedef struct
{
    BYTE type;    //8位类型字段
    BYTE code;    //8位代码字段
    USHORT cksum;    //16位校验和
    USHORT id;    //16位标识符
    USHORT seq;    //16位序列号
} ICMP_HEADER;

//报文解码结构
typedef struct
{
    USHORT usSeqNo;        //序列号
    DWORD dwRoundTripTime;    //往返时间
    in_addr dwIPaddr;        //返回报文的IP地址
}DECODE_RESULT;

//计算网际校验和函数
USHORT checksum(USHORT *pBuf,int iSize)
{
    unsigned long cksum=0;
    while(iSize>1)
    {
        cksum+=*pBuf++;
        iSize-=sizeof(USHORT);
    }
    if(iSize)
    {
        cksum+=*(UCHAR *)pBuf;
    }
    cksum=(cksum>>16)+(cksum&0xffff);
    cksum+=(cksum>>16);
    return (USHORT)(~cksum);
}

//对数据包进行解码
BOOL DecodeIcmpResponse(char * pBuf,int iPacketSize,DECODE_RESULT &DecodeResult,BYTE ICMP_ECHO_REPLY,BYTE  ICMP_TIMEOUT)
{

    //检查数据报大小的合法性
    /*作者*/
    IP_HEADER* pIpHdr = (IP_HEADER*)pBuf;
    /*作者*/
    int iIpHdrLen = pIpHdr->hdr_len * 4;//计算ip头部长度

    /*作者*/
    if (iPacketSize < (int)(iIpHdrLen+sizeof(ICMP_HEADER)))
        return FALSE;
    /*作者*/



    //根据ICMP报文类型提取ID字段和序列号字段
    ICMP_HEADER *pIcmpHdr=(ICMP_HEADER *)(pBuf+iIpHdrLen);
    USHORT usID,usSquNo;
    if(pIcmpHdr->type==ICMP_ECHO_REPLY)    //ICMP回显应答报文
    {
        usID=pIcmpHdr->id;        //报文ID
        usSquNo=pIcmpHdr->seq;    //报文序列号
    }
    else if(pIcmpHdr->type==ICMP_TIMEOUT)//ICMP超时差错报文
    {
        char * pInnerIpHdr=pBuf+iIpHdrLen+sizeof(ICMP_HEADER);                    //载荷中的IP头
        int iInnerIPHdrLen=((IP_HEADER *)pInnerIpHdr)->hdr_len*4;                //载荷中的IP头长
        ICMP_HEADER * pInnerIcmpHdr=(ICMP_HEADER *)(pInnerIpHdr+iInnerIPHdrLen);//载荷中的ICMP头
        usID=pInnerIcmpHdr->id;        //报文ID
        usSquNo=pInnerIcmpHdr->seq;    //序列号
    }
    else
    {
        return false;
    }

    //检查ID和序列号以确定收到期待数据报
    if(usID!=(USHORT)GetCurrentProcessId()||usSquNo!=DecodeResult.usSeqNo)
    {
        return false;
    }

    //记录IP地址并计算往返时间
    DecodeResult.dwIPaddr.s_addr=pIpHdr->sourceIP;
    DecodeResult.dwRoundTripTime=GetTickCount()-DecodeResult.dwRoundTripTime;

    //处理正确收到的ICMP数据报
    if (pIcmpHdr->type == ICMP_ECHO_REPLY ||pIcmpHdr->type == ICMP_TIMEOUT)
    {
        //输出往返时间信息
        if(DecodeResult.dwRoundTripTime)
            cout<<"      "<>IpAddress;

    //将命令行转化为IP地址
     u_long ulDestIP=inet_addr(IpAddress);
     //u_long ulDestIP=inet_addr(argv[1]);

    if(ulDestIP==INADDR_NONE)
    {
        //转换不成功时按域名解析
        hostent * pHostent=gethostbyname(IpAddress);
        //hostent * pHostent=gethostbyname(argv[1]);
        if(pHostent)
        {
            ulDestIP=(*(in_addr*)pHostent->h_addr).s_addr;
        }
        else
        {
            //cout<<"输入的IP地址或域名无效!"<type=ICMP_ECHO_REQUEST;            //类型为请求回显
    pIcmpHeader->code=0;                //代码字段为0
    pIcmpHeader->id=(USHORT)GetCurrentProcessId();    //ID字段为当前进程号
    memset(IcmpSendBuf+sizeof(ICMP_HEADER),'E',DEF_ICMP_DATA_SIZE);//数据字段

    USHORT usSeqNo=0;            //ICMP报文序列号
    int iTTL=1;            //TTL初始值为1
    BOOL bReachDestHost=FALSE;    //循环退出标志
    int iMaxHot=DEF_MAX_HOP;    //循环的最大次数
    DECODE_RESULT DecodeResult;    //传递给报文解码函数的结构化参数
    while(!bReachDestHost&&iMaxHot--)
    {
        //设置IP报头的TTL字段
        setsockopt(sockRaw,IPPROTO_IP,IP_TTL,(char *)&iTTL,sizeof(iTTL));
        cout<cksum=0;    //校验和先置为0
        ((ICMP_HEADER *)IcmpSendBuf)->seq=htons(usSeqNo++);    //填充序列号
        ((ICMP_HEADER *)IcmpSendBuf)->cksum=checksum((USHORT *)IcmpSendBuf,sizeof(ICMP_HEADER)+DEF_ICMP_DATA_SIZE);//计算校验和

        //记录序列号和当前时间
        DecodeResult.usSeqNo=((ICMP_HEADER*)IcmpSendBuf)->seq;    //当前序号
        cout<<" DecodeResult.usSeqNo:  "<< DecodeResult.usSeqNo<

你可能感兴趣的:(tracert 实现伪代码)