18,362
社区成员
发帖
与我相关
我的任务
分享
//返回值:1表示网络状态正常 ,0表示网络状态异常
// ==================ping的实现部分==================
int doit(int argc, char* argv[])
{
if (argc < 2) {
cerr << "usage: ping <host>" << endl;
return 1;
}
// 装载ICMP.DLL连接库
HINSTANCE hIcmp = LoadLibrary("ICMP.DLL");
if (hIcmp == 0) {
cerr << "Unable to locate ICMP.DLL!" << endl;
return 2;
}
// 查找给定机器的IP地址信息
struct hostent* phe;
if ((phe = gethostbyname(argv[1])) == 0) {
cerr << "Could not find IP address for " << argv[1] << endl;
return 3;
}
// 定义函数三个指针类型
typedef HANDLE (WINAPI* pfnHV)(VOID);
typedef BOOL (WINAPI* pfnBH)(HANDLE);
typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD,
PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD); // evil, no?
//定义三个指针函数
pfnHV pIcmpCreateFile;
pfnBH pIcmpCloseHandle;
pfnDHDPWPipPDD pIcmpSendEcho;
//从ICMP.DLL中得到函数入口地址
pIcmpCreateFile = (pfnHV)GetProcAddress(hIcmp, "IcmpCreateFile");
pIcmpCloseHandle = (pfnBH)GetProcAddress(hIcmp, "IcmpCloseHandle");
pIcmpSendEcho = (pfnDHDPWPipPDD)GetProcAddress(hIcmp, "IcmpSendEcho");
if ((pIcmpCreateFile == 0) || (pIcmpCloseHandle == 0) ||
(pIcmpSendEcho == 0)) {
cerr << "Failed to get proc addr for function." << endl;
return 4;
}
// 打开ping服务
HANDLE hIP = pIcmpCreateFile();
if (hIP == INVALID_HANDLE_VALUE) {
cerr << "Unable to open ping service." << endl;
return 5;
}
// 构造ping数据包
char acPingBuffer[64];
memset(acPingBuffer, '\xAA', sizeof(acPingBuffer));
PIP_ECHO_REPLY pIpe = (PIP_ECHO_REPLY)GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT,
sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer));
if (pIpe == 0) {
cerr << "Failed to allocate global ping packet buffer." << endl;
return 6;
}
pIpe->Data = acPingBuffer;
pIpe->DataSize = sizeof(acPingBuffer);
// 发送ping数据包
DWORD dwStatus = pIcmpSendEcho(hIP, *((DWORD*)phe->h_addr_list[0]),
acPingBuffer, sizeof(acPingBuffer), NULL, pIpe,
sizeof(IP_ECHO_REPLY) + sizeof(acPingBuffer), 5000);
if (dwStatus != 0) {
cerr << "Addr: " <<
int(LOBYTE(LOWORD(pIpe->Address))) << "." <<
int(HIBYTE(LOWORD(pIpe->Address))) << "." <<
int(LOBYTE(HIWORD(pIpe->Address))) << "." <<
int(HIBYTE(HIWORD(pIpe->Address))) << ", " <<
"RTT: " << int(pIpe->RoundTripTime) << "ms, " <<
"TTL: " << int(pIpe->Options.Ttl) << endl;
}
else {
cerr << "Error obtaining info from ping packet." << endl;
cout<<dwStatus<<" "<<GetLastError()<<endl;
}
// 关闭,回收资源
GlobalFree(pIpe);
FreeLibrary(hIcmp);
return 0;
}
HANDLE hIcmpFile;
if ((hIcmpFile = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
{
printf("\tUnable to open file.\n");
return;
}
else
printf("\tFile created.\n");
char *SendData = "Data Buffer";
LPVOID ReplyBuffer;
ReplyBuffer = (VOID*) malloc(sizeof(ICMP_ECHO_REPLY) + sizeof(SendData));
if ((dwRetVal = IcmpSendEcho(hIcmpFile,
inet_addr("123.456.789.0"),
SendData, sizeof(SendData),
NULL, ReplyBuffer,
sizeof(ReplyBuffer) + sizeof(ICMP_ECHO_REPLY),
1000)) != 0) {
printf("\tReceived %ld messages.\n", dwRetVal);
printf("\tMessage: %s\n", ReplyBuffer);
}
else {
printf("\tCall to IcmpSendEcho() failed.\n");
printf("\tError: %ld\n", GetLastError());
}
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
typedef struct icmp_hdr
{
unsigned char icmp_type; // 消息类型
unsigned char icmp_code; // 代码
unsigned short icmp_checksum; // 校验和
// 下面是回显头
unsigned short icmp_id; // 用来惟一标识此请求的ID号,通常设置为进程ID
unsigned short icmp_sequence; // 序列号
unsigned long icmp_timestamp; // 时间戳
} ICMP_HDR, *PICMP_HDR;
typedef struct _IPHeader // 20字节的IP头
{
UCHAR iphVerLen; // 版本号和头长度(各占4位)
UCHAR ipTOS; // 服务类型
USHORT ipLength; // 封包总长度,即整个IP报的长度
USHORT ipID; // 封包标识,惟一标识发送的每一个数据报
USHORT ipFlags; // 标志
UCHAR ipTTL; // 生存时间,就是TTL
UCHAR ipProtocol; // 协议,可能是TCP、UDP、ICMP等
USHORT ipChecksum; // 校验和
ULONG ipSource; // 源IP地址
ULONG ipDestination; // 目标IP地址
} IPHeader, *PIPHeader;
USHORT checksum(USHORT* buff, int size);
BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv = TRUE);
int main()
{
// 目的IP地址,即要Ping的IP地址
char szDestIp[] = "127.0.0.1"; // 127.0.0.1
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2,2);
if(::WSAStartup(sockVersion, &wsaData) != 0)
{
return -1;
}
// 创建原始套节字
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
// 设置接收超时
SetTimeout(sRaw, 1000, TRUE);
// 设置目的地址
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0);
dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);
// 创建ICMP封包
char buff[sizeof(ICMP_HDR) + 32];
ICMP_HDR* pIcmp = (ICMP_HDR*)buff;
// 填写ICMP封包数据
pIcmp->icmp_type = 8; // 请求一个ICMP回显
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
// 填充数据部分,可以为任意
memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
// 开始发送和接收ICMP封包
USHORT nSeq = 0;
char recvBuf[1024];
SOCKADDR_IN from;
int nLen = sizeof(from);
while(TRUE)
{
static int nCount = 0;
int nRet;
if(nCount++ == 4)
break;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{
printf(" sendto() failed: %d \n", ::WSAGetLastError());
return -1;
}
nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
if(nRet == SOCKET_ERROR)
{
if(::WSAGetLastError() == WSAETIMEDOUT)
{
printf("Request timed out\n");
continue;
}
printf(" recvfrom() failed: %d\n", ::WSAGetLastError());
return -1;
}
// 下面开始解析接收到的ICMP封包
int nTick = ::GetTickCount();
if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
{
printf(" Too few bytes from %s \n", ::inet_ntoa(from.sin_addr));
}
// 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头
ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
if(pRecvIcmp->icmp_type != 0) // 回显
{
printf(" nonecho type %d recvd \n", pRecvIcmp->icmp_type);
return -1;
}
if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())
{
printf(" someone else's packet! \n");
return -1;
}
printf(" %d bytes from %s:", nRet, inet_ntoa(from.sin_addr));
printf(" icmp_seq = %d. ", pRecvIcmp->icmp_sequence);
printf(" time: %d ms", nTick - pRecvIcmp->icmp_timestamp);
printf(" \n");
::Sleep(1000);
}
return 0;
}
USHORT checksum(USHORT* buff, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buff++;
size -= sizeof(USHORT);
}
// 是奇数
if(size)
{
cksum += *(UCHAR*)buff;
}
// 将32位的chsum高16位和低16位相加,然后取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
BOOL SetTimeout(SOCKET s, int nTime, BOOL bRecv)
{
int ret = ::setsockopt(s, SOL_SOCKET,
bRecv ? SO_RCVTIMEO : SO_SNDTIMEO, (char*)&nTime, sizeof(nTime));
return ret != SOCKET_ERROR;
}
// 以太工作室 东东
// 函数:Ping
// 参数:
// szTarget目标地址(可以是域名、IP地址)
// dwTime返回时间;如果是超时,等于INFINITE
BOOL Ping(LPCTSTR szTarget, DWORD &dwTime)
{
BOOL bSuccess = FALSE;
dwTime = INFINITE;
if(szTarget == NULL)
{
TRACE0("Target Is NULL\n");
return FALSE;
}
TCHAR szCmdLine[80];
if(_sntprintf(szCmdLine, sizeof(szCmdLine) / sizeof(TCHAR),
_T("ping.exe -n 1 %s"), szTarget) == sizeof(szCmdLine) / sizeof(TCHAR))
{
TRACE0("Target Is Too Long\n");
return FALSE;
}
HANDLE hWritePipe = NULL;
HANDLE hReadPipe = NULL;
HANDLE hWriteShell = NULL;
HANDLE hReadShell = NULL;
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if(CreatePipe(&hReadPipe, &hReadShell, &sa, 0)
&& CreatePipe(&hWriteShell, &hWritePipe, &sa, 0))
{
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = hWriteShell;
si.hStdOutput = hReadShell;
si.hStdError = hReadShell;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
int nMin = -1, nMax = -1, nAvg = -1;
if(CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
if(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0)
{
TCHAR szBuffer[1024];
DWORD dwBytes;
if(ReadFile(hReadPipe, szBuffer, sizeof(szBuffer), &dwBytes, NULL))
{
szBuffer[dwBytes] = '\0';
LPTSTR lpszTime = NULL;
lpszTime = _tcsstr(szBuffer, _T("Request timed out"));
if(lpszTime == NULL)
{
lpszTime = _tcsstr(szBuffer, _T("Minimum"));
if(lpszTime != NULL)
{
if(_stscanf(lpszTime, _T("Minimum = %dms, Maximum = %dms, Average = %dms"),
&nMin, &nMax, &nAvg) == 3)
{
TRACE3("%d, %d, %d\n", nMin, nMax, nAvg);
dwTime = nAvg;
bSuccess = TRUE;
}
}
else
{
TRACE0("PING FORMAT is Error\n");
}
}
else
{
TRACE0("PING is Time Out\n");
bSuccess = TRUE;
}
}
}
else
{
TRACE1("Process(%d) is Time Out\n", pi.dwProcessId);
TerminateProcess(pi.hProcess, 0);
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
TRACE3(_T("Minimum = %dms, Maximum = %dms, Average = %dms\n"), nMin, nMax, nAvg);
}
}
if(hWritePipe != NULL)
CloseHandle(hWritePipe);
if(hReadPipe != NULL)
CloseHandle(hReadPipe);
if(hWriteShell != NULL)
CloseHandle(hWriteShell);
if(hReadShell != NULL)
CloseHandle(hReadShell);
return bSuccess;
}