自己实现的 PING 命令···

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include <Windows.h>
#include <iostream>
#include <stdio.h>

// PingSock.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"

/****************************************************************/
/*        类型(0或8)|        代码(0)|            校验和        |*/
/****************************************************************/
/*                标识符            |                序号        |*/
/****************************************************************/
/*                            timestamp数据                           |*/
/****************************************************************/

#define DEF_BUF_SIZE 1024
#define IP_HEADER_SIZE 20
#define ICMP_HEADER_SIZE (sizeof(ICMP_HEADER))//在 下面的typedef 中有定义
#define CIMP_DATA_SIZE 32//ICMP HEADER AND THE DATA SIZE OF IT
#define ICMP_PACK_SIZE (ICMP_HEADER_SIZE + CIMP_DATA_SIZE)
using namespace std;
typedef char _TCHAR;

typedef struct _ICMP_HEADER
{
    BYTE nType;
    BYTE nCode;
    USHORT nCheckSum;

    USHORT nId;
    USHORT nSequence;

    UINT nTimeStamp;
}ICMP_HEADER, * PICMP_HEADER;


USHORT GetCheckSum(LPBYTE lpBuf, DWORD dwSize);
BOOL Ping(char * lpDestIp);
char zsRcv[DEF_BUF_SIZE];

int main()
{
    char szDestIp[ICMP_HEADER_SIZE] = {0};
    while(1)
    {
        cout<< "insert your IP" <<endl;
        strcpy(szDestIp,"202.202.43.125");
        Ping(szDestIp);
    }
}
USHORT GetCheckSum(LPBYTE lpBuf, DWORD dwsize)
{
    DWORD sum = 0;
    USHORT * tik = (USHORT *)lpBuf;
    while(dwsize>1)
    {
        sum += *tik++ ;
        dwsize-=2;
    }
    if (dwsize ==1)
    {
        sum+=*((USHORT*)tik);
    }
    //sum's higher 16bits add sum's lower 16bits;
    sum = //最低位与最高位直接相加了··
        (sum>>16)
        +
        (sum & 0xffff);
    sum+=(sum>>16);//上一步产生了进位;向右移动之后再次进行 16位相加 ;
    return (USHORT)~sum;
/*        DWORD dwCheckSum = 0;// 4 char
     USHORT* lpWord = (USHORT*)lpBuf; // 2 char
 
     while( dwSize > 1)
     {
         dwCheckSum += *lpWord++;
         dwSize -= 2;
     }
 
     if(1 == dwSize)
         dwCheckSum += *((USHORT*)lpWord);
 
     dwCheckSum = ( dwCheckSum >> 16) + ( dwCheckSum & 0xffff);
     dwCheckSum+=(dwCheckSum>>16);//上一步
     return (USHORT)(~dwCheckSum);*/
}
BOOL Ping(char * lpDestIp)
{
    /*
    1 = 封装icmp——头
    2 = 初始化 socket ; send to receive from
    */
    // :: 这里是 ICMP 的头 !!
    char ICMPPack[ICMP_PACK_SIZE] = {0};
    PICMP_HEADER pICM = (PICMP_HEADER)ICMPPack;
    USHORT DD;
    pICM->nType = 8;
    pICM->nCode = 0;
    pICM->nId = DD=(USHORT)::GetCurrentProcessId();
    pICM->nCheckSum = 0;
    pICM->nTimeStamp = 0;
    memset(&pICM[ICMP_HEADER_SIZE],'E',sizeof(CIMP_DATA_SIZE));

    //SOCKET INITIAL
    SOCKADDR_IN sock_sendto_addr;
    sock_sendto_addr.sin_addr.S_un.S_addr = inet_addr(lpDestIp);
    sock_sendto_addr.sin_family = AF_INET;
    sock_sendto_addr.sin_port = htons(0);

    WORD wV = MAKEWORD(2,2);
    {
        WSADATA wsaDTA;
        if(::WSAStartup(wV,&wsaDTA) !=0)
        {
            cout<<"wsastartup wrong"<<endl;
            return false;
        }
    }

    SOCKET sdt_skt = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
    if(INVALID_SOCKET == sdt_skt )
    {
        int k = ::GetLastError();
        cout << "there is sth wrong here"<<endl
            << "the erro-coder is "<< k <<endl;
    }    
     int nTime = 1000;
     int nRet = ::setsockopt( sdt_skt, SOL_SOCKET, SO_RCVTIMEO,(char*)(&nTime),sizeof(nTime));
    //多次 发送消息 然后回收消息 RCVFRM

    SOCKADDR_IN RECV_ADDR;
    char rcvbuf[DEF_BUF_SIZE];
    for(int i = 0;i<4;++i)
    {
        pICM->nCheckSum = 0;
        pICM->nTimeStamp = ::GetTickCount();// 发出的时间
        pICM->nSequence = i;

        USHORT AZ= GetCheckSum((LPBYTE) ICMPPack,  ICMP_PACK_SIZE);
        cout<<(char *)ICMPPack<<endl;
        pICM->nCheckSum=AZ;
            /**/int nRet = ::sendto(sdt_skt,ICMPPack,ICMP_PACK_SIZE,0,(sockaddr *)&sock_sendto_addr,sizeof(sock_sendto_addr));
            
            if(nRet == SOCKET_ERROR)
            {
                cout << "there is sth wrong here"<<endl
                    << "the erro-coder is "<<
                    ::GetLastError() <<endl;
            }
            int a = sizeof(RECV_ADDR);

            /**/int Recv = ::recvfrom(sdt_skt,rcvbuf,DEF_BUF_SIZE,0,(SOCKADDR *)&RECV_ADDR,&a);
            if(SOCKET_ERROR == Recv)
            {
                if(::WSAGetLastError() == WSAETIMEDOUT)
                {
                    cout << "request time out"<<endl;
                    continue;
                }
                else
                {
                    cout<<"rcv error"<<endl;
                    continue;
                }
            }

            int nTime = ::GetTickCount()-pICM->nTimeStamp;//接收到的时间
            int rGet = Recv - IP_HEADER_SIZE - ICMP_HEADER_SIZE;//真正接收到的字节数

            // print out the result ??
            //verify  if it is the same ICMP PACK
            PICMP_HEADER pHeader = (PICMP_HEADER)(rcvbuf + IP_HEADER_SIZE);//OFFSET THE POINTER TO THE HEAD OF ICMP;

            if(pHeader->nType != 0)
            {
                cout<<"not valid"<<endl;
                return false;
            }
            USHORT ADZ = pHeader->nId;
            if(pHeader->nId != ::GetCurrentProcessId())
            {
                cout<<"this is the wrong packet"<<endl;
                return false;
            }

            cout<<"return "<< rGet <<"BYTES FROM "<< inet_ntoa(RECV_ADDR.sin_addr)<<"rtti = "<<nTime<<endl;
    }
    ::Sleep(1000);
    ::closesocket(sdt_skt);
    ::WSACleanup();
    system("pause");
    return 0;
}


/*

最浪费时间的是 那个校验和算法;http://eric43.blog.163.com/blog/static/36627706201121212915639/
<< 的优先级比 + 的低级 优先级 还是个大问题啊 ··http://zh.wikipedia.org/wiki/C%E5%92%8CC%2B%2B%E9%81%8B%E7%AE%97%E5%AD%90
http://zh.wikipedia.org/wiki/C%E5%92%8CC%2B%2B%E9%81%8B%E7%AE%97%E5%AD%90
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值