[TCP/IP详解学习中] ping程序

TCP/IP详解学习中

//  WinPing.cpp : Defines the entry point for the console application.
//
//  USAGE:
//    WinPing 192.168.58.251
//    WinPing www.infogo.com.cn
//
#include  " stdafx.h "
#include 
" stdlib.h "
#include 
" winsock2.h "
#pragma  comment ( lib , "ws2_32.lib" )

#define  MyWebSite "www.infogo.com.cn"

typedef 
struct  icmp_hdr
{
 unsigned 
char  icmp_type;          // 消息类型
 unsigned char  icmp_code;          // 消息代码
 unsigned short icmp_checksum;      // 检验和

 unsigned 
short icmp_id;            // 用来惟一标识此请求的ID号
 unsigned short icmp_sequence;      // 序列号
 unsigned long  imcp_timestamp;     // 时间戳
}
 ICMP_HDR ,  * PICMP_HDR;

typedef 
struct  ip_hdr
{
 unsigned 
char iphdr[20]; // IP报文头,具体怎么样忘了,反正20个字节
}
 IP_HDR ,  * PIP_HDR;

unsigned 
short  checksum( unsigned  short *  buf ,  int  len )
{
 unsigned 
long sum = 0;
 
while( len > 1 )
 
{
  sum 
+= *buf;
  
++buf;
  len 
-= sizeof(unsigned short);
 }

 
if( len )
 
{
  sum 
+= *(UCHAR*)buf;
 }

 sum 
= (sum>>16+ (sum&0xffff);
 sum 
+= (sum>>16);
 
return (USHORT)(~sum);
}


void  usage(  int  argc ,  char *  argv[] )
{
 
char szFileName[1024= 0 };
 
char szFileExt[1024]  = 0 };
 _splitpath( argv[
0] , NULL , NULL , szFileName , szFileExt );
 strcat( szFileName , szFileExt );

 printf( 
"USAGE: " );
 printf( 
"%s <dest> " , szFileName );
 printf( 
" " );
 printf( 
"EXAMPLE: " );
 printf( 
" %s 192.168.0.1 " , szFileName );
 printf( 
" %s %s " , szFileName , MyWebSite );
 printf( 
" " );
}


const   char *  GetErrorMsg( DWORD dwErrorCode )
{
 
static char msg[1024= 0 };
 
return msg;
}


int  main( int  argc,  char *  argv[])
{
 
// 检查是否有足够的参数
 if( argc < 2 )
 
{
  usage( argc , argv );
  
return 1;
 }


 DWORD destIp 
= 0;
 
char destName[1024= 0 };
 SOCKET s;
 
struct sockaddr_in destAddr = 0 };
 
char icmpBuf[ sizeof(ICMP_HDR)+32 ] = 0 };
 PICMP_HDR pIcmp 
= (PICMP_HDR)icmpBuf;
 
int nSeq = 0;
 
int nTryTime = 0;
 
char recvBuf[1024= 0 };
 
int recvTimeOut = 1000;
 
int sendTimeOut = 1000;
 
int nRet = 0;

 
// SOCKET初始化
 WSADATA wsa = 0 };
 WSAStartup( MAKEWORD(
2,2) , &wsa );

 
// 获取目标主机IP
 strcpy( destName , argv[1] );
 
struct hostent* dest = gethostbyname( destName );
 
if( dest == NULL )
 
{
  printf( 
"错误: 无法解析主机名<%s>. " , destName );
  
goto programEnd;
 }

 destIp 
= *(DWORD*)dest->h_addr_list[0];
 printf( 
" Pinging [ %s ] %s width %d bytes of data. " ,
  dest
->h_name ,
  inet_ntoa(
*(in_addr*)&destIp) ,
  
32
  );
 
// 生成目标主机地址
 destAddr.sin_family = AF_INET;
 destAddr.sin_addr.s_addr 
= destIp;
 destAddr.sin_port 
= htons(0);

 
// 创建ICMP封包
 pIcmp->icmp_type = 8// 请求回显
 pIcmp->icmp_code = 0;
 pIcmp
->icmp_id = (unsigned short)::GetCurrentProcessId();
 pIcmp
->icmp_sequence = 0;
 memset( 
&icmpBuf[ sizeof(ICMP_HDR) ] , 'Z' , 32 );

 
// 创建原始套接字
 s = socket( AF_INET , SOCK_RAW , IPPROTO_ICMP );
 
if( s == SOCKET_ERROR )
 
{
  printf( 
"错误: 创建套接字失败. " );
  printf( 
"原因: %d %s " , GetLastError() , GetErrorMsg( GetLastError() ) );
  
goto programEnd;
 }


 
// 设置接收超时
 nRet = setsockopt( s , SOL_SOCKET , SO_RCVTIMEO , (const char*)&recvTimeOut , sizeof(recvTimeOut) );
 
// 设置发送超时
 nRet = setsockopt( s , SOL_SOCKET , SO_SNDTIMEO , (const char*)sendTimeOut , sizeof(sendTimeOut) );

 nTryTime 
= 0;
 
while( nTryTime < 5 )
 
{
  
int nRet = 0;
  
int nLen = 0;

  
++nTryTime;
  
++nSeq;
  pIcmp
->icmp_checksum = 0;
  pIcmp
->icmp_sequence = nSeq;
  pIcmp
->imcp_timestamp = ::GetTickCount();
  pIcmp
->icmp_checksum = checksum( (USHORT*)icmpBuf , sizeof(ICMP_HDR)+32 );
  
// 发送ICMP封包
  nRet = ::sendto( s , icmpBuf , sizeof(ICMP_HDR)+32 , 0 , (SOCKADDR*)&destAddr , sizeof(destAddr) );
  
if( nRet == SOCKET_ERROR )
  
{
   printf( 
"错误: 发送ICMP报文失败. " );
   printf( 
"原因: %d %s " , GetLastError() , GetErrorMsg( GetLastError() ) );
   
goto programEnd;
  }

  
// 接收应答包
  memset( recvBuf , 0 , sizeof(recvBuf) );
  nLen 
= sizeof(destAddr);
  nRet 
= ::recvfrom( s , recvBuf , sizeof(recvBuf) , 0 , (SOCKADDR*)&destAddr , &nLen );
  
if( nRet == SOCKET_ERROR )
  
{
   
if( ::WSAGetLastError() == WSAETIMEDOUT )
   
{
    printf( 
"Request timed out. " );
   }

   
else
   
{
    printf( 
"错误: 接收ICMP报文失败. " );
    printf( 
"原因: %d %s " , GetLastError() , GetErrorMsg( GetLastError() ) );
   }

  }

  
else
  
{
   
// 解析应答包
   DWORD nCurrTime = ::GetTickCount();
   
if( nRet < sizeof(IP_HDR) + sizeof(ICMP_HDR) )
   
{
    printf( 
"Too few bytes from %s. " , ::inet_ntoa(destAddr.sin_addr) );
   }

   
else
   
{
    PICMP_HDR pRecvIcmp 
= (PICMP_HDR)&recvBuf[ sizeof(IP_HDR) ];
    
if( pRecvIcmp->icmp_type != 0 )
    
{
     printf( 
"not echo type %d recved. " , pRecvIcmp->icmp_type );
    }

    
else
    
{
     
if( pRecvIcmp->icmp_id != ::GetCurrentProcessId() )
     
{
      printf( 
"someone else's packet. " );
     }

     
else
     
{
      printf( 
"%d bytes from %s: " , nRet , inet_ntoa(destAddr.sin_addr) );
      printf( 
"icmp_seq = %d. " , pRecvIcmp->icmp_sequence );
      printf( 
"time: %d ms. " , nCurrTime - pRecvIcmp->imcp_timestamp );
     }

    }

   }

  }

  Sleep( 
1000 );
 }
 // END WHILE

programEnd:
 WSACleanup();
 
return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值