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;
}
//
// 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;
}