激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C/C++ - C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

2021-12-14 15:19盧奕冰2017 C/C++

這篇文章主要介紹了C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能,Ping命令被送到本地計(jì)算機(jī)的IP軟件,該命令永不退出該計(jì)算機(jī),本文給大家介紹的非常詳細(xì),需要的朋友參考下吧

ping 127.0.0.1: 這個Ping命令被送到本地計(jì)算機(jī)的IP軟件,該命令永不退出該計(jì)算機(jī)。

localhost是個操作系統(tǒng)的網(wǎng)絡(luò)保留名,是127.0.0.1的別名。

ping www.baidu.com――對這個域名執(zhí)行Ping命令,你的計(jì)算機(jī)必須先將域名轉(zhuǎn)換成IP地址,通常是通過DNS服務(wù)器。

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

 

(一)main.cpp文件

// ConsoleApplication3.cpp : 定義控制臺應(yīng)用程序的入口點(diǎn)。
//
//程序應(yīng)用:  ping命令是向目的主機(jī)發(fā)送ICMP報(bào)文,檢驗(yàn)本地主機(jī)和遠(yuǎn)程的目的主機(jī)是否連接

#include <winsock2.h>
#include <stdio.h>
#include "ping.h"

int main(void)
{
	CPing objPing;                 //CPing類與對象

	char *szDestIP = "127.0.0.1";  //字符IP地址  //127.0.0.1 這個Ping命令被送到本地計(jì)算機(jī)的IP軟件,該命令永不退出該計(jì)算機(jī)。localhost是個操作系統(tǒng)的網(wǎng)絡(luò)保留名,是127.0.0.1的別名。//ping www.baidu.com――對這個域名執(zhí)行Ping命令,你的計(jì)算機(jī)必須先將域名轉(zhuǎn)換成IP地址,通常是通過DNS服務(wù)器。
	PingReply reply;	           //PingReply類與對象

	printf("Pinging %s with %d bytes of data:\n", szDestIP, DEF_PACKET_SIZE);	//ping 遠(yuǎn)端IP地址,32字節(jié)的數(shù)據(jù)
	
	while (TRUE)
	{
		objPing.Ping(szDestIP, &reply);//遠(yuǎn)端IP地址不為空(NULL),就返回true表示需要響應(yīng)報(bào)文。遠(yuǎn)端IP空時不需要響應(yīng)報(bào)文false。
		printf("Reply from %s: bytes=%d time=%ldms TTL=%ld\n", szDestIP, reply.m_dwBytes, reply.m_dwRoundTripTime, reply.m_dwTTL);  //字節(jié)數(shù),時間,TTL生存時間
		Sleep(500);
	}

	return 0;
}

 

(二)ping.h文件

(1)IP頭結(jié)構(gòu)體:

IHL:首部長度。因?yàn)镮P的頭部不是定長的,所以需要這個信息進(jìn)行IP包的解析,從而找到Data字段的起始點(diǎn)。   

另外注意這個IHL是以4個字節(jié)為單位的,所以首部實(shí)際長度是IHL*4字節(jié)。

Time to Live:生存時間,這個就是TTL了。

Data:這部分是IP包的數(shù)據(jù),也就是ICMP的報(bào)文內(nèi)容。

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

//1.IP頭結(jié)構(gòu)體:20字節(jié)
struct IPHeader
{
	BYTE m_byVerHLen;		//4位版本Version+4位首部長度IHL	1B
	BYTE m_byTOS;			//服務(wù)類型						1B=16b
	USHORT m_usTotalLen;	//總長度						2B=16b
	USHORT m_usID;			//標(biāo)識							2B=16b
	USHORT m_usFlagFragOffset; //3位標(biāo)志+13位片偏移=16位	2B=16b
	BYTE m_byTTL;			//TTL	生存時間    			1B=8b
	BYTE m_byProtocol;		//協(xié)議							1B=8b   為1時表示是ICMP報(bào)文
	USHORT m_usHChecksum;	//首部檢驗(yàn)和					2B=16b
	ULONG m_ulSrcIP;		//源IP地址						4B=32b
	ULONG m_ulDestIP;		//目的IP地址					4B=32b
};

(2)ICMP頭結(jié)構(gòu)體:

類型Type、代碼Code、校驗(yàn)和、標(biāo)識符、序列號、ICMP數(shù)據(jù)

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

//ICMP報(bào)文由首部8B和數(shù)據(jù)段組成。
//首部為定長的8個字節(jié),前4個字節(jié)是通用部分(類型1B/代碼1B/校驗(yàn)和2B),后4個字節(jié)隨報(bào)文類型的不同有所差異。

//2.ICMP頭結(jié)構(gòu)體 (標(biāo)準(zhǔn)ICMP頭為8字節(jié))
struct ICMPHeader
{
	BYTE m_byType;		 //類型   1B   type=8表示響應(yīng)請求報(bào)文,type=0表示響應(yīng)應(yīng)答報(bào)文。
	BYTE m_byCode;		 //代碼   1B   與type組合,表示具體的信息
	USHORT m_usChecksum; //檢驗(yàn)和 2B   整個ICMP報(bào)文的檢驗(yàn)和,包括Type、Code、...、Data。
	USHORT m_usID;		 //標(biāo)識符 2B=16bits	用于標(biāo)識本進(jìn)程
	USHORT m_usSeq;		 //序列號 2B=16bits	用于判斷回顯應(yīng)答數(shù)據(jù)報(bào)。
	ULONG m_ulTimeStamp; //時間戳(非標(biāo)準(zhǔn)ICMP頭部)4B   //統(tǒng)計(jì)ping的往返時間的做法是,在ICMP報(bào)文的Data區(qū)域?qū)懭?個字節(jié)的時間戳。在收到應(yīng)答報(bào)文時,取出這個時間戳與當(dāng)前的時間對比即可。
};

(3)ICMP響應(yīng)報(bào)文結(jié)構(gòu)體:

//3.ICMP回答報(bào)文結(jié)構(gòu)體
struct PingReply
{
	USHORT m_usSeq;         //ICMP包的序列號  2B
	DWORD m_dwRoundTripTime;//時間差		  4B  (word是2字節(jié))
	DWORD m_dwBytes;        //數(shù)據(jù)所占字節(jié)數(shù)  4B
	DWORD m_dwTTL;          //TTL生存時間     4B
};

(4)Ping類及相關(guān)變量的定義:

//類
class CPing
{
//公共變量
public:
	CPing();  //構(gòu)造函數(shù)
	~CPing(); //析構(gòu)函數(shù)

	BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);
	BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);

//私有變量
private:
	BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);
	USHORT CalCheckSum(USHORT *pBuffer, int nSize);//計(jì)算檢驗(yàn)和
	ULONG GetTickCountCalibrate();  //計(jì)算毫秒級別的時間差

private:
	SOCKET m_sockRaw;			//需要監(jiān)聽的socket
	WSAEVENT m_event;           //網(wǎng)絡(luò)事件對象
	USHORT m_usCurrentProcID;   //當(dāng)前進(jìn)程發(fā)出的報(bào)文
	char *m_szICMPData;			//ICMP(Internet Control Message Protocol,網(wǎng)際控制報(bào)文協(xié)議)
	BOOL m_bIsInitSucc;			//初始化成功

private:
	static USHORT s_usPacketSeq;  //序列號++(16位=2字節(jié))
};

 

(三)ping.cpp文件

#include "ping.h"
#include <iostream>

USHORT CPing::s_usPacketSeq = 0;

(1)char *m_szICMPData; BOOL m_bIsInitSucc;

//::表示類作用域。為避免不同的類有名稱相同的成員而采用作用域的方式進(jìn)行區(qū)分。
CPing::CPing() :m_szICMPData(NULL), m_bIsInitSucc(FALSE)
{
	WSADATA WSAData;
	//WSAStartup(MAKEWORD(2, 2), &WSAData);
	if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
	{
		printf("WSAStartup() failed: %d\n", GetLastError());  /*如果初始化不成功則報(bào)錯,GetLastError()返回發(fā)生的錯誤信息*/
		return;
	}

	m_event = WSACreateEvent();  //創(chuàng)建一個網(wǎng)絡(luò)事件對象(HANDLE m_event)。   //返回一個手工重置的事件對象句柄 (HANDLE hEventObject)
	m_usCurrentProcID = (USHORT)GetCurrentProcessId();  //當(dāng)前進(jìn)程ID

	/*ICMP必須使用原始套接字進(jìn)行設(shè)計(jì),要手動設(shè)置IP的頭部和ICMP的頭部并行校驗(yàn)*/
	m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);  //創(chuàng)建一個監(jiān)聽的socket (SOCKET m_sockRaw)  //當(dāng)IP報(bào)頭中的協(xié)議字段值為1時,就說明這是一個ICMP報(bào)文。

	if (m_sockRaw == INVALID_SOCKET) //無效套接字
	{
		std::cerr << "WSASocket() failed:" << WSAGetLastError() << std::endl;  //10013 以一種訪問權(quán)限不允許的方式做了一個訪問套接字的嘗試。
	}
	else  //是ICMP報(bào)文,令初始化成功,為ICMP數(shù)據(jù)分配內(nèi)存
	{
		WSAEventSelect(m_sockRaw, m_event, FD_READ);  //調(diào)用WSAEventSelect將監(jiān)聽的socket(m_sockRaw)與該事件(m_event)進(jìn)行關(guān)聯(lián)。WSAEventSelect(套接字,網(wǎng)絡(luò)事件對象,需要關(guān)注的事件)
		m_bIsInitSucc = TRUE;

		m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader));  //為ICMPData分配內(nèi)存

		//ping命令的工作原理是:向網(wǎng)絡(luò)上的另一個主機(jī)系統(tǒng)發(fā)送ICMP報(bào)文,如果指定系統(tǒng)得到了報(bào)文,它將把報(bào)文一模一樣地傳回給發(fā)送者

		if (m_szICMPData == NULL)
		{
			m_bIsInitSucc = FALSE;
		}
	}
}


CPing::~CPing()
{
	WSACleanup();

	if (NULL != m_szICMPData)
	{
		free(m_szICMPData);
		m_szICMPData = NULL;
	}
}

(2)BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);

BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
	if (NULL != szDestIP)	//遠(yuǎn)端IP非空
	{
		return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout);  //項(xiàng)目 -> 屬性 -> C/C++ > SDL檢查:否。――修改VS配置,告訴它我就要用舊函數(shù)。inet_pton() or InetPton()
	}
	return FALSE;           //遠(yuǎn)端IP為空,false
}

(3)BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);

1.//判斷初始化是否成功

2.//配置套接字SOCKET

3.//構(gòu)建ICMP包

4.//填補(bǔ)ICMP首部

5.//發(fā)送ICMP請求報(bào)文(ping請求)

6.//判斷是否需要接收響應(yīng)報(bào)文

7.//等待網(wǎng)絡(luò)事件接收響應(yīng)報(bào)文

BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
	//判斷初始化是否成功
	if (!m_bIsInitSucc)
	{
		return FALSE;   //初始化沒成功
	}

	//配置套接字SOCKET
	sockaddr_in sockaddrDest;                    //sockaddr_in是internet環(huán)境下的套接字地址。定義在ws2def.h中的結(jié)構(gòu)體
	sockaddrDest.sin_family = AF_INET;           //地址族(Address Family):網(wǎng)絡(luò)類型
	sockaddrDest.sin_addr.s_addr = dwDestIP;     //32位IP地址(4字節(jié))
	int nSockaddrDestSize = sizeof(sockaddrDest);//大小

	//構(gòu)建ICMP包
	int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader);  //ICMP包長度:32+ICMP頭
	ULONG ulSendTimestamp = GetTickCountCalibrate();    //發(fā)送時間戳(毫秒級)
	USHORT usSeq = ++s_usPacketSeq;						//2字節(jié),++0
	memset(m_szICMPData, 0, nICMPDataSize);				//數(shù)據(jù),長度。memset()初始化內(nèi)存:
	//memset(* Dst, int Val, size_t Size):將指針變量Dst所指向的前Size字節(jié)的內(nèi)存單元用一個“整數(shù)”Val替換。

	//填補(bǔ)ICMP首部
	ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData;
	pICMPHeader->m_byType = ECHO_REQUEST;   //類型。Type:8,Code:0:表示回顯請求報(bào)文(ping請求)。   Type:0,Code:0:表示回顯回答報(bào)文(ping應(yīng)答)
	pICMPHeader->m_byCode = 0;              //代碼
	pICMPHeader->m_usID = m_usCurrentProcID;//標(biāo)識符
	pICMPHeader->m_usSeq = usSeq;           //本報(bào)的序列號
	pICMPHeader->m_ulTimeStamp = ulSendTimestamp;//發(fā)送時間戳(非標(biāo)準(zhǔn)ICMP頭部)
	pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize);//計(jì)算檢驗(yàn)和    //TCP/IP協(xié)議棧使用的校驗(yàn)算法:對16位的數(shù)據(jù)進(jìn)行累加計(jì)算,并返回計(jì)算結(jié)果
	
	//――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
	//發(fā)送ICMP請求報(bào)文(ping請求)
	if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR)
	{
		return FALSE;  //套接字錯誤
	}

	//判斷是否需要接收響應(yīng)報(bào)文
	if (pPingReply == NULL)
	{
		return TRUE;
	}

	char recvbuf[256] = { "\0" };  //初始化

	while (TRUE)    //接收響應(yīng)報(bào)文
	{
		//等待網(wǎng)絡(luò)事件
		if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)  //等待事件(m_event)。
			//WSAWaitForMultipleEvents(事件對象數(shù)組里邊的個數(shù)為1,事件對象數(shù)組,等待類型為FALSE表示事件數(shù)組里至少有一個信號就返回,等待的超時時間為100,當(dāng)系統(tǒng)的執(zhí)行隊(duì)列有I/O例程要執(zhí)行時不返回)
		{
			WSANETWORKEVENTS netEvent;
			WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent);   //m_event = WSACreateEvent();
			//事件發(fā)生時,調(diào)用WSAEnumNetworkEvents,檢測指定的socket上的網(wǎng)絡(luò)事件,并將關(guān)聯(lián)信息保存在netEvent中。
			//WSAEnumNetworkEvents(SOCKET s,WSAEVENT hEventObject,LPWSANETWORKEVENTS lpNetworkEvents)
			//當(dāng)調(diào)用WSAEnumNetworkEvents函數(shù)成功后,它會將我們指定的socket和事件對象所關(guān)聯(lián)的網(wǎng)絡(luò)事件的信息保存到LPWSANETWORKEVENTS這個結(jié)構(gòu)體里去,根據(jù)這個結(jié)構(gòu)體我們就可以判斷是否是我們所關(guān)注的網(wǎng)絡(luò)事件已經(jīng)發(fā)生了。

			//如果是FD_READ,讀的網(wǎng)絡(luò)事件發(fā)生了,那就調(diào)用recv函數(shù)進(jìn)行操作。
			//若是FD_CLOSE,關(guān)閉的網(wǎng)絡(luò)事件發(fā)生了,就調(diào)用closesocket將socket關(guān)掉,在數(shù)組里將其置零等操作。
			if (netEvent.lNetworkEvents & FD_READ)  //有網(wǎng)絡(luò)事件,且可讀,那就recv收數(shù)啊
			{
				ULONG nRecvTimestamp = GetTickCountCalibrate();   //計(jì)算開始發(fā)送的時間
				int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize);  //從遠(yuǎn)端IP處收數(shù)。
				if (nPacketSize != SOCKET_ERROR)
				{
					//ICMP協(xié)議是IP層的一個協(xié)議,但是由于差錯報(bào)告在發(fā)送給報(bào)文源發(fā)方時可能也要經(jīng)過若干子網(wǎng),因此牽涉到路由選擇等問題,所以ICMP報(bào)文需通過IP協(xié)議來發(fā)送。
					
					//ICMP數(shù)據(jù)報(bào)的數(shù)據(jù)發(fā)送前需要兩級封裝:首先添加ICMP報(bào)頭形成ICMP報(bào)文,再添加IP報(bào)頭形成IP數(shù)據(jù)報(bào)。
					//拆解封裝:IP數(shù)據(jù)報(bào)去掉IP報(bào)頭,剩下ICMP報(bào)文,再去掉ICMP報(bào)頭,就是ICMP數(shù)據(jù)報(bào)了。
					IPHeader *pIPHeader = (IPHeader*)recvbuf;
					USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4);     //(4位版本+4位首部長度)&0xf,然后乘4  //IP頭部20字節(jié)
					ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen);

					if (pICMPHeader->m_usID == m_usCurrentProcID //是當(dāng)前進(jìn)程發(fā)出的報(bào)文
						&& pICMPHeader->m_byType == ECHO_REPLY   //是響應(yīng)報(bào)文類型(Type=0)
						&& pICMPHeader->m_usSeq == usSeq         //是本次請求報(bào)文的響應(yīng)報(bào)文
						)
					{
						pPingReply->m_usSeq = usSeq;   //ICMP包的序列號
						pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp; //當(dāng)應(yīng)答返回時,用當(dāng)前時間減去存放在ICMP報(bào)文中的時間值,即是往返時間。
						pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader);//數(shù)據(jù)大?。赫鼣?shù)據(jù)-IP頭-ICMP頭
						pPingReply->m_dwTTL = pIPHeader->m_byTTL;  //TTL生存時間
						return TRUE;
					}
				}
			}
		}
		//超時
		if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout)//時間戳(非標(biāo)準(zhǔn)ICMP頭部)
		{
			return FALSE;
		}
	}
}

WSA連網(wǎng)事件流程圖

C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能

(4)計(jì)算檢驗(yàn)和

//計(jì)算檢驗(yàn)和    // TCP/IP協(xié)議棧使用的校驗(yàn)算法是比較經(jīng)典的,對16位的數(shù)據(jù)進(jìn)行累加計(jì)算,并返回計(jì)算結(jié)果
USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize)       //CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize);
{
	unsigned long ulCheckSum = 0;   //4B=32b    //(1)將檢驗(yàn)和字段置為0

	while (nSize > 1)
	{
		ulCheckSum += *pBuffer++;   //數(shù)值相加	//(2)把需校驗(yàn)的數(shù)據(jù)看成以16位為單位的數(shù)字組成,依次進(jìn)行求和,并存到32位的整型中
		nSize -= sizeof(USHORT);    //長度相減
	}
	if (nSize)
	{
		ulCheckSum += *(UCHAR*)pBuffer; 
	}

	ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);  //高位相加  //(3)把求和結(jié)果中的高16位(進(jìn)位)加到低16位上,如果還有進(jìn)位,重復(fù)
	ulCheckSum += (ulCheckSum >> 16);                         //將溢出位加入

	return (USHORT)(~ulCheckSum);    //返回值:取反                       //(4)將這個32位的整型按位取反,并強(qiáng)制轉(zhuǎn)換為16位整型(截?cái)?后返回
}


/*
附錄:如何計(jì)算檢驗(yàn)和
ICMP中檢驗(yàn)和的計(jì)算算法為:
1、將檢驗(yàn)和字段置為0
2、把需校驗(yàn)的數(shù)據(jù)看成以16位為單位的數(shù)字組成,依次進(jìn)行二進(jìn)制反碼求和
3、把得到的結(jié)果存入檢驗(yàn)和字段中
所謂二進(jìn)制反碼求和,就是:
1、將源數(shù)據(jù)轉(zhuǎn)成反碼
2、0 + 0 = 0   0 + 1 = 1   1 + 1 = 0進(jìn)1
3、若最高位相加后產(chǎn)生進(jìn)位,則最后得到的結(jié)果要加1
在實(shí)際實(shí)現(xiàn)的過程中,比較常見的代碼寫法是:
1、將檢驗(yàn)和字段置為0
2、把需校驗(yàn)的數(shù)據(jù)看成以16位為單位的數(shù)字組成,依次進(jìn)行求和,并存到32位的整型中
3、把求和結(jié)果中的高16位(進(jìn)位)加到低16位上,如果還有進(jìn)位,重復(fù)第3步[實(shí)際上,這一步最多會執(zhí)行2次]
4、將這個32位的整型按位取反,并強(qiáng)制轉(zhuǎn)換為16位整型(截?cái)?后返回
*/

(5)計(jì)算毫秒級別的時間差

//計(jì)算毫秒級別的時間差。返回值是unsigned long級別的
ULONG CPing::GetTickCountCalibrate()
{
	static ULONG s_ulFirstCallTick = 0;
	static LONGLONG s_ullFirstCallTickMS = 0;

	SYSTEMTIME systemtime;		//系統(tǒng)時間SYSTEMTIME與tm類似,不過多了一項(xiàng)wMilliseconds。
	FILETIME filetime;		    //文件時間FILETIME與time_t類似,是64位整型,不過FILETIME是以100納秒(ns)為單位。
	GetLocalTime(&systemtime);  //GetLocalTime獲得當(dāng)前的本地時間,GetSystemTime函數(shù)獲得當(dāng)前的UTC時間,兩個時間存在著時差。
	SystemTimeToFileTime(&systemtime, &filetime);//UTC的SYSTEMTIME時間 轉(zhuǎn)換為對應(yīng)的 本地的FILETIME時間
	
	LARGE_INTEGER liCurrentTime;
	liCurrentTime.HighPart = filetime.dwHighDateTime;
	liCurrentTime.LowPart = filetime.dwLowDateTime;
	LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;

	if (s_ulFirstCallTick == 0)
	{
		s_ulFirstCallTick = GetTickCount();  //返回(retrieve)從操作系統(tǒng)啟動所經(jīng)過(elapsed)的毫秒數(shù)。用GetTickCount()計(jì)算毫秒級的時間差是不靠譜的!
	}

	if (s_ullFirstCallTickMS == 0)
	{
		s_ullFirstCallTickMS = llCurrentTimeMS;
	}

	return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);//   當(dāng)前時間ms - 第一次回應(yīng)時間ms
}

到此這篇關(guān)于C++代碼實(shí)現(xiàn)網(wǎng)絡(luò)Ping功能的文章就介紹到這了,更多相關(guān)C++網(wǎng)絡(luò)Ping內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/luyibing2017/article/details/119597300

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 午夜视频中文字幕 | 一级性色 | 看免费5xxaaa毛片 | 日本精品婷婷久久爽一下 | 成人三级电影在线 | 久久久午夜电影 | 亚洲综合色视频在线观看 | 亚洲日韩精品欧美一区二区 | 亚洲视频黄 | 91久久国产露脸精品国产护士 | 久久男人视频 | 久久国产精品久久久久久 | 91精品国产综合久久婷婷香 | 黄色毛片视频在线观看 | 亚洲射情| 久久久婷婷一区二区三区不卡 | av日韩在线免费观看 | 高颜值美女啪啪 | 亚洲综合视频在线播放 | 亚洲一区二区三区在线 | 国产精品欧美久久久久一区二区 | 久久综合久久精品 | 在线 日本 制服 中文 欧美 | 夜夜b| 精品在线观看一区二区三区 | 久久综合艹 | 日本黄色大片免费观看 | 日本看片一区二区三区高清 | 久久久国产精品免费观看 | 免费看毛片网站 | 精品成人免费一区二区在线播放 | 免费播放欧美毛片 | 日韩精品中文字幕一区二区 | 91在线视频在线观看 | 在线看小早川怜子av | 日本不卡一区二区三区在线 | 91国内精品久久久久免费影院 | 亚洲欧美国产高清va在线播放 | 午夜伦情电午夜伦情电影 | 亚洲四播房 | 爱草成年 |