小标
2018-09-04
来源 :
阅读 2401
评论 0
摘要:本文主要向大家介绍了VC编程之vc实现ping,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。
本文主要向大家介绍了VC编程之vc实现ping,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。
//ping.h
#ifndef _CPING_H_
#define _CPING_H_
#include
#include
#pragma pack(1)
#define ICMP_ECHOREPLY 0
#define ICMP_ECHOREQ 8
#define REQ_DATASIZE 32 // Echo 请求数据的大小
class
CPing
{
public:
//ping host, nRetries-ping次数
bool
Ping(LPCSTR
pstrHost, UINT
nRetries = 4);
void
Result(int* nElapseTime, float* fMissPack = NULL, u_char* cTTL = NULL);
//void Result(CPing::REQ_RESULT& result);
private:
int
WaitForEchoReply(SOCKET s);
//ICMP回应的请求和回答函数
int
SendEchoRequest(SOCKET, LPSOCKADDR_IN);
DWORD
RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);
u_short in_cksum(u_short *addr, int
len);
private:
struct
REQ_RESULT
{
int
nElapseTime; //请求响应时间。
u_char cTTL; //请求TTL(生存时间)
float
fMissPack; //丢包率
};
REQ_RESULT m_Result;
};
// IP Header -- RFC 791
typedef
struct tagIPHDR
{
u_char VIHL; // Version and IHL
u_char TOS; // Type Of Service
short
TotLen; // Total Length
short
ID; // Identification
short
FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct
in_addr iaSrc; // Internet Address - Source
struct
in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR;
// ICMP Header - RFC 792
typedef
struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char
Data; // Data
}ICMPHDR, *PICMPHDR;
// ICMP Echo Request
typedef
struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD
dwTime;
char
cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
// ICMP Echo Reply
typedef
struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char
cFiller[256];
}ECHOREPLY, *PECHOREPLY;
#pragma pack()
#endif
//ping.cpp
#include "ping.h"
#pragma comment(lib, "ws2_32.lib")
bool
CPing::Ping(LPCSTR
pstrHost, UINT
nRetries)
{
//创建一个Raw套节字
SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if
(rawSocket == INVALID_SOCKET)
{
int
err = WSAGetLastError();
return
false;
}
int
nNetTimeout = 1000;//1秒
//发送时限
setsockopt(rawSocket, SOL_SOCKET, SO_SNDTIMEO, (char
*)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char
*)&nNetTimeout,sizeof(int));
//获得主机信息
LPHOSTENT lpHost = gethostbyname(pstrHost);
if
(lpHost == NULL)
{
return
false;
}
//构造目标套节字地址信息
struct
sockaddr_in saDest;
struct
sockaddr_in saSrc;
saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
saDest.sin_family = AF_INET;
saDest.sin_port = 3077;//0;
DWORD
dwTimeSent;
u_char cTTL;
int
nRet;
int
nRecvNum = 0;
int
nTotalTime = 0;
//多次ping
for
(UINT nLoop = 0; nLoop < nRetries; ++nLoop)
{
//发送ICMP回应请求
if
((nRet = SendEchoRequest(rawSocket, &saDest)) < 0)
{
break;
}
if
((nRet = WaitForEchoReply(rawSocket)) == SOCKET_ERROR)
{
break;
}
if
(nRet)
{
//获得回应
if
( (dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL)) < 0)
{
nRet = dwTimeSent;
break;
}
//计算时间
nTotalTime += GetTickCount() - dwTimeSent;
//Sleep(1000);
++nRecvNum;
}
}
closesocket(rawSocket);
if
(nRecvNum > 0 && nRet >= 0)
{
m_Result.nElapseTime = nTotalTime/nRetries;
m_Result.cTTL = cTTL;
m_Result.fMissPack = (float)(nRetries - nRecvNum)/nRetries;
return
true;
}
return
false;
}
//发送ICMPECHO数据包请求
int
CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
static
ECHOREQUEST echoReq;
static
int nId = 1;
static
int nSeq = 1;
int
nRet;
//构造回应请求
echoReq.icmpHdr.Type = ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.Seq = nSeq++;
for
(nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ‘ ‘+nRet;
//保存发送时间
echoReq.dwTime = GetTickCount();
echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));
//发送请求
nRet = sendto(s,
(LPSTR)&echoReq,
sizeof(ECHOREQUEST),
0,
(LPSOCKADDR)lpstToAddr,
sizeof(SOCKADDR_IN));
//检查返回值
if
(nRet == SOCKET_ERROR)
{
}
return
(nRet);
}
//接收ICMPECHO数据包回应
DWORD
CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
ECHOREPLY echoReply;
int
nRet;
int
nAddrLen = sizeof(struct
sockaddr_in);
//接收请求回应
nRet = recvfrom(s,
(LPSTR)&echoReply,
sizeof(ECHOREPLY),
0,
(LPSOCKADDR)lpsaFrom,
&nAddrLen);
//检查返回值
if
(nRet == SOCKET_ERROR)
{
return
nRet;
}
//返回发送的时间
*pTTL = echoReply.ipHdr.TTL;
return(echoReply.echoRequest.dwTime);
}
//等待回应
int
CPing::WaitForEchoReply(SOCKET s)
{
struct
timeval Timeout;
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;
return(select(1, &readfds, NULL, NULL, &Timeout));
}
//转换地址
u_short CPing::in_cksum(u_short *addr, int
len)
{
register
int nleft = len;
register
u_short *w = addr;
register
u_short answer;
register
int sum = 0;
while( nleft > 1 ) {
sum += *w++;
nleft -= 2;
}
if( nleft == 1 ) {
u_short u = 0;
*(u_char *)(&u) = *(u_char *)w ;
sum += u;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return
(answer);
}
void
CPing::Result(int* nElapseTime, float* fMissPack, u_char* cTTL)
{
if
(nElapseTime)
{
*nElapseTime = m_Result.nElapseTime;
}
if
(fMissPack)
{
*fMissPack = m_Result.fMissPack;
}
if
(cTTL)
{
*cTTL = m_Result.cTTL;
}
}
//main.cpp
#include
#include
#include
#include "ping.h"
int main(int
argn, char
*argv[])
{
WORD
wVersionRequested;
WSADATA wsaData;
int
err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
CPing ping;
bool
bResult = false;
if
(argn == 2)
{
bResult = ping.Ping(argv[1]);
}
else
{
bResult = ping.Ping("www.baidu.com");
}
std::cout << "result : "
<< bResult << std::endl;
if
(bResult)
{
int
nTime;
u_char nTTL;
float
fMiss;
ping.Result(&nTime, &fMiss, &nTTL);
std::cout << "time : "
<< nTime << " TTL : "
<< (int)nTTL << " miss : "
<< fMiss*100 << "% "
<< std::endl;
}
return
0;
}
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!
喜欢 | 1
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号