【TCP/IP】C语言实现Ping小程序
2012-12-23 17:03
1011 查看
Ping程序一般用来测试一台主机是否可达,该程序发送一份ICMP回显请求报文给主机,并等待返回ICMP回显 应答。
一般来说,如果不能Ping到某主机,那么就不能Telnet或者FTP到那台主机。反过来,如果不能Telnet到某台主机,那么通常可以用Ping程序来确定问题出在哪里。Ping程序还可以检测出到这台主机的往返时间,以表明该主机里我们有“多远”。大多数的TCP/IP实现都在内核中直接支持Ping服务器。
ICMP回显请求和回显应答报文如下所示
定义ICMP报头数据结构
下面使用Socket实现Ping小程序。
一般来说,如果不能Ping到某主机,那么就不能Telnet或者FTP到那台主机。反过来,如果不能Telnet到某台主机,那么通常可以用Ping程序来确定问题出在哪里。Ping程序还可以检测出到这台主机的往返时间,以表明该主机里我们有“多远”。大多数的TCP/IP实现都在内核中直接支持Ping服务器。
ICMP回显请求和回显应答报文如下所示
/****************************************************************/ /* 类型(0或8)| 代码(0)| 校验和 |*/ /****************************************************************/ /* 标识符 | 序号 |*/ /****************************************************************/ /* 选项数据 |*/ /****************************************************************/
定义ICMP报头数据结构
typedef struct _ICMP_HEADER{ BYTE nType; BYTE nCode; USHORT nCheckSum; USHORT nId; USHORT nSequence; UINT nTimeStamp; }ICMP_HEADER,*PICMP_HEADER;
下面使用Socket实现Ping小程序。
// PingSock.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") #include <Windows.h> //定义默认缓冲区长度 #define DEF_BUF_SIZE 1024 #define IP_HEADER_SIZE 20 #define ICMP_HEADER_SIZE (sizeof(ICMP_HEADER)) #define ICMP_DATA_SIZE 32 #define ICMP_PACK_SIZE (ICMP_HEADER_SIZE + ICMP_DATA_SIZE) typedef struct _ICMP_HEADER{ BYTE nType; BYTE nCode; USHORT nCheckSum; USHORT nId; USHORT nSequence; UINT nTimeStamp; }ICMP_HEADER,*PICMP_HEADER; char szInfo[DEF_BUF_SIZE] = {0}; USHORT GetCheckSum(LPBYTE lpBuf, DWORD dwSize); BOOL Ping(char* lpDestIp); int _tmain(int argc, _TCHAR* argv[]) { char szDestIp[DEF_BUF_SIZE] = {0} ; while ( scanf ( "%s", szDestIp) ) Ping ( szDestIp ) ; return 0; } USHORT GetCheckSum(LPBYTE lpBuf, DWORD dwSize) { DWORD dwCheckSum = 0; USHORT* lpWord = (USHORT*)lpBuf; while( dwSize > 1) { dwCheckSum += *lpWord++; dwSize -= 2; } if(1 == dwSize) dwCheckSum += *((USHORT*)lpBuf); dwCheckSum = ( dwCheckSum >> 16) + ( dwCheckSum & 0xffff); return (USHORT)(~dwCheckSum); } BOOL Ping(char* lpDestIp) { SOCKADDR_IN DestAddr; DestAddr.sin_family = AF_INET; DestAddr.sin_addr.S_un.S_addr = inet_addr(lpDestIp); DestAddr.sin_port = htons(0); //创建ICMP请求包 char ICMPPack[ICMP_PACK_SIZE] = {0}; PICMP_HEADER pICMPHeader = (PICMP_HEADER)ICMPPack; pICMPHeader->nType = 8; pICMPHeader->nCode = 0; pICMPHeader->nId = (USHORT)::GetCurrentProcessId(); pICMPHeader->nCheckSum = 0; pICMPHeader->nTimeStamp = 0; memset(&(ICMPPack[ICMP_HEADER_SIZE]),'E',ICMP_DATA_SIZE); //初始化WinSock WORD wVersionRequested = MAKEWORD(2,2); WSADATA wsaData; if(WSAStartup(wVersionRequested,&wsaData) != 0) { return FALSE; } //创建初始套接字 SOCKET RawSock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if(INVALID_SOCKET == RawSock) { printf("create raw socket error\n"); return FALSE; } int nTime = 1000; int nRet = ::setsockopt( RawSock, SOL_SOCKET, SO_RCVTIMEO,(char*)(&nTime),sizeof(nTime)); char szRecvBuf [ DEF_BUF_SIZE] ; SOCKADDR_IN SourSockAddr ; for(int i = 0; i < 4; i++) { pICMPHeader->nCheckSum = 0; pICMPHeader->nTimeStamp = ::GetTickCount(); pICMPHeader->nSequence = i; pICMPHeader->nCheckSum = GetCheckSum ( (LPBYTE)ICMPPack, ICMP_PACK_SIZE ) ; int nRet = ::sendto( RawSock, ICMPPack, ICMP_PACK_SIZE, 0, (SOCKADDR*)&DestAddr, sizeof(DestAddr)); if ( nRet == SOCKET_ERROR ) { printf ( "sendto error!\n" ) ; return FALSE ; } // 接收ICMP响应 int nLen = sizeof(SourSockAddr) ; nRet = ::recvfrom ( RawSock, szRecvBuf, DEF_BUF_SIZE,0,(SOCKADDR*)&SourSockAddr, &nLen ) ; if ( nRet == SOCKET_ERROR ) { if ( ::WSAGetLastError() == WSAETIMEDOUT ) { printf ( "Request Timeout\n" ) ; continue ; } else { printf ( "recvfrom error!\n" ) ; return FALSE ; } } int nTime = ::GetTickCount() - pICMPHeader->nTimeStamp ; int nRealSize = nRet - IP_HEADER_SIZE - ICMP_HEADER_SIZE ; if ( nRealSize < 0 ) { printf ( "To less recv bytes!\n" ) ; continue ; } // 检测是否当前所发出的ICMP响应包 PICMP_HEADER pRecvHeader = (PICMP_HEADER)(szRecvBuf+IP_HEADER_SIZE) ; if ( pRecvHeader->nType != 0 ) { printf ( "Not ICMP respond type!\n" ) ; return FALSE ; } if ( pRecvHeader->nId != ::GetCurrentProcessId () ) { printf ( "not valid id!\n" ) ; return FALSE ; } printf ( "%d bytes replay from %s : bytes=%d time=%dms\n", \ nRet, inet_ntoa(SourSockAddr.sin_addr), nRealSize, nTime ) ; ::Sleep ( 1000 ) ; } closesocket ( RawSock ) ; WSACleanup () ; return TRUE ; }
相关文章推荐
- 【TCP/IP】C语言实现Ping小程序
- C语言实现PING程序
- 用C语言实现Ping程序功能
- 用C语言实现Ping程序功能
- windows下ping程序使用C语言实现
- 基于C语言与原始套接字实现Ping程序
- 基于C语言实现的Ping程序
- Ping程序在TCP/IP中的应用
- 003.同时Ping多个IP(select实现IO复用,信号计时),ping程序升级版
- ping程序-c语言实现
- 用C语言实现Ping程序功能
- (转载)用C语言实现Ping程序功能
- TCP/IP之四:ping程序
- 多连接的tcp/ip程序实现
- linux下TCP/IP实现简单聊天程序
- Linux下用C语言实现Ping程序功能
- 用C语言实现Ping程序功能
- Time protocol实现的基于TCP/IP的网络对时程序
- 用C语言实现Ping程序功能(转)
- Linux下用C语言实现Ping程序功能