Ping功能是测试网络是否连接的有效方式。通常我们需要通过ping来验证网络连接是否正常,这就需要我们经常用到ping功能。
ping是有一定的阻塞,如果频繁使用会导致应用程序出现阻塞现象,为了避免这种情况的发生,我们这里举例用线程的方式对网络进行ping来验证网络是否连接正常:
- UI布局
- 添加按键处理:OnBn1ClickedSendOnBn2ClickedClearOnBn3ClickedReturn
- 添加线程处理:
DWORD myPingDlg::onMyThread1(LPVOID lpParameter) { // TODO: Add your control notification handler code here int i; BOOL bResult; CString str; CPing objPing; MyStruct1 *pPingMessage; i = 0; pPingMessage = (MyStruct1*)lpParameter; do { i++; bResult = objPing.Ping(pPingMessage->pDestIP, &pPingMessage->reply, pPingMessage->dwBytes); if (bResult == TRUE) { ::PostMessage(pPingMessage->hwnd, WM_PING, 0, (LPARAM)pPingMessage); } else { ::PostMessage(pPingMessage->hwnd, WM_PING, 1, (LPARAM)i); } Sleep(1000); } while (bEndless); ::PostMessage(pPingMessage->hwnd, WM_PING, 2, NULL); return 0; }
- 线程向对话框传递消息处理:
LRESULT myPingDlg::onPingMessage(WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); WORD i; CString str,org; MyStruct1 *pMyPingInfo; UpdateData(true); org = m_edit1_ping; i = (WORD)wParam; if (i == 0) { pMyPingInfo = (MyStruct1*)lParam; str.Format(_T("Reply from : bytes=%d time=%ldms TTL=%ld "), pMyPingInfo->reply.m_dwBytes,pMyPingInfo->reply.m_dwRoundTripTime,pMyPingInfo->reply.m_dwTTL); str.Insert(11, pMyPingInfo->pDestIP); } else if (i == 1) { str.Format(_T("Failed: Ping did not response at %d package. "), lParam); } else if (i == 2) { str = _T(" Ping Test STOP !!! "); CButton*pbutton = (CButton*)this->GetDlgItem(IDC_BUTTON1); SetDlgItemText(IDC_BUTTON1, _T("PingRetry")); SetDlgItemText(IDC_BUTTON3, _T("Return")); pbutton->EnableWindow(TRUE); CEdit*pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT3); pEditCtl->EnableWindow(TRUE); pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT4); pEditCtl->EnableWindow(TRUE); } SetDlgItemText(IDC_EDIT1, org+str); CEdit*pCtl = (CEdit*)this->GetDlgItem(IDC_EDIT1); pCtl->LineScroll(pCtl->GetLineCount()); return 0; }
- 完整代码:
// myPingDlg.cpp : implementation file // #include "stdafx.h" #include "MicrohardTest.h" #include "myPingDlg.h" #include "afxdialogex.h" //user #include "MicrohardTestDlg.h" #include "Source.h" #include <winsock2.h> #include <stdio.h> #include <string.h> // myPingDlg dialog static BOOL bEndless; IMPLEMENT_DYNAMIC(myPingDlg, CDialogEx) myPingDlg::myPingDlg(CWnd* pParent /*=NULL*/) : CDialogEx(myPingDlg::IDD, pParent) , m_edit1_ping(_T("")) , m_edit2_web(_T("192.168.168.1"))/*dw=0xc0a8a801; ping 192.168.168.1 -l 65000 –t*/ , m_dw_edit4_bytes_of_package(32) { } myPingDlg::~myPingDlg() { } void myPingDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT1, m_edit1_ping); DDX_Text(pDX, IDC_EDIT3, m_edit2_web); DDX_Text(pDX, IDC_EDIT4, m_dw_edit4_bytes_of_package); DDV_MinMaxUInt(pDX, m_dw_edit4_bytes_of_package, 1, 65000); } BEGIN_MESSAGE_MAP(myPingDlg, CDialogEx) ON_BN_CLICKED(IDC_BUTTON3, &myPingDlg::OnBn3ClickedReturn) ON_BN_CLICKED(IDC_BUTTON1, &myPingDlg::OnBn1ClickedSend) ON_BN_CLICKED(IDC_BUTTON2, &myPingDlg::OnBn2ClickedClear) ON_MESSAGE(WM_PING, onPingMessage) END_MESSAGE_MAP() // myPingDlg message handlers void myPingDlg::OnBn3ClickedReturn() { // TODO: Add your control notification handler code here if (bEndless == TRUE) { bEndless = FALSE; } else { myPingDlg::OnOK(); CMicrohardTestDlg mdlg; mdlg.DoModal(); } } void myPingDlg::OnBn1ClickedSend() { // TODO: Add your control notification handler code here int nCount = 0; char *szDestIP; char szIp0[100][100]; CString str; CPing objPing; char szDomain[256] = { 0 }; //Get ip address from domain UpdateData(true); if (m_dw_edit4_bytes_of_package < 1){ SetDlgItemText(IDC_EDIT4, "1"); return; } else if (m_dw_edit4_bytes_of_package>65000) { SetDlgItemText(IDC_EDIT4,"65000"); return; } GetDlgItem(IDC_EDIT3)->GetWindowText(str); strcpy_s(szDomain, str); BOOL bResult = objPing.GetIpByDomainName(szDomain, szIp0, &nCount); if (bResult == TRUE) { szDestIP = &szIp0[0][0]; DWORD dwIP = ntohl(inet_addr(szDestIP)); CIPAddressCtrl*pIP = (CIPAddressCtrl*)this->GetDlgItem(IDC_IPADDRESS2); pIP->SetAddress(dwIP); if (nCount != 0) { CButton*pbutton = (CButton*)this->GetDlgItem(IDC_BUTTON1); pbutton->EnableWindow(FALSE); SetDlgItemText(IDC_BUTTON1, _T("PingRunning")); SetDlgItemText(IDC_BUTTON3, _T("PingStop")); str.Format(_T("Ping address: with %d bytes of a package: "), m_dw_edit4_bytes_of_package); str.Insert(13, szDestIP); m_edit1_ping = str; HANDLE hThread; MyStruct1 *pmystruct = new MyStruct1; pmystruct->hwnd = m_hWnd; pmystruct->pDestIP = szDestIP; pmystruct->dwBytes = m_dw_edit4_bytes_of_package; bEndless = TRUE; hThread = CreateThread(NULL, 0, onMyThread1, (LPVOID)pmystruct, 0, NULL); CloseHandle(hThread); CEdit*pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT3); pEditCtl->EnableWindow(FALSE); pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT4); pEditCtl->EnableWindow(FALSE); } else { m_edit1_ping = _T("Failed! Domain Can't Parser !!!"); } } else { m_edit1_ping = _T("WSA Startup failed !!!"); } UpdateData(FALSE); } void myPingDlg::OnBn2ClickedClear() { // TODO: Add your control notification handler code here UpdateData(TRUE); if (m_edit1_ping.IsEmpty()==false) { m_edit1_ping = _T(""); UpdateData(FALSE); } } BOOL myPingDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { switch (pMsg->wParam) { case VK_ESCAPE: { if (bEndless == TRUE) { bEndless = FALSE; } return TRUE; break; } case VK_RETURN: { return TRUE; break; } default: break; } } return CDialog::PreTranslateMessage(pMsg); } DWORD myPingDlg::onMyThread1(LPVOID lpParameter) { // TODO: Add your control notification handler code here int i; BOOL bResult; CString str; CPing objPing; MyStruct1 *pPingMessage; i = 0; pPingMessage = (MyStruct1*)lpParameter; do { i++; bResult = objPing.Ping(pPingMessage->pDestIP, &pPingMessage->reply, pPingMessage->dwBytes); if (bResult == TRUE) { ::PostMessage(pPingMessage->hwnd, WM_PING, 0, (LPARAM)pPingMessage); } else { ::PostMessage(pPingMessage->hwnd, WM_PING, 1, (LPARAM)i); } Sleep(1000); } while (bEndless); ::PostMessage(pPingMessage->hwnd, WM_PING, 2, NULL); return 0; } LRESULT myPingDlg::onPingMessage(WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(wParam); UNREFERENCED_PARAMETER(lParam); WORD i; CString str,org; MyStruct1 *pMyPingInfo; UpdateData(true); org = m_edit1_ping; i = (WORD)wParam; if (i == 0) { pMyPingInfo = (MyStruct1*)lParam; str.Format(_T("Reply from : bytes=%d time=%ldms TTL=%ld "), pMyPingInfo->reply.m_dwBytes,pMyPingInfo->reply.m_dwRoundTripTime,pMyPingInfo->reply.m_dwTTL); str.Insert(11, pMyPingInfo->pDestIP); } else if (i == 1) { str.Format(_T("Failed: Ping did not response at %d package. "), lParam); } else if (i == 2) { str = _T(" Ping Test STOP !!! "); CButton*pbutton = (CButton*)this->GetDlgItem(IDC_BUTTON1); SetDlgItemText(IDC_BUTTON1, _T("PingRetry")); SetDlgItemText(IDC_BUTTON3, _T("Return")); pbutton->EnableWindow(TRUE); CEdit*pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT3); pEditCtl->EnableWindow(TRUE); pEditCtl = (CEdit*)this->GetDlgItem(IDC_EDIT4); pEditCtl->EnableWindow(TRUE); } SetDlgItemText(IDC_EDIT1, org+str); CEdit*pCtl = (CEdit*)this->GetDlgItem(IDC_EDIT1); pCtl->LineScroll(pCtl->GetLineCount()); return 0; }
#pragma once #include "Source.h" // myPingDlg dialog #define WM_PING WM_USER+2 struct MyStruct1 { HWND hwnd; char *pDestIP; PingReply reply; DWORD dwTimeOut; DWORD dwBytes; }; class myPingDlg : public CDialogEx { DECLARE_DYNAMIC(myPingDlg) public: myPingDlg(CWnd* pParent = NULL); // standard constructor virtual ~myPingDlg(); // Dialog Data enum { IDD = IDD_DIALOG2 }; private: static DWORD WINAPI onMyThread1(LPVOID lpParameter); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg LRESULT onPingMessage(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() public: CString m_edit1_ping; afx_msg void OnBn3ClickedReturn(); afx_msg void OnBn1ClickedSend(); afx_msg void OnBn2ClickedClear(); CString m_edit2_web; DWORD m_dw_edit4_bytes_of_package; };
- Ping处理代码:
#include "stdafx.h" #include "Source.h" #include <iostream> USHORT CPing::s_usPacketSeq = 0; CPing::CPing() :m_szICMPData(NULL), m_bIsInitSucc(FALSE) { WSADATA WSAData; if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0) { /*如果初始化不成功则报错,GetLastError()返回发生的错误信息*/ printf("WSAStartup() failed: %d ", GetLastError()); return; } m_event = WSACreateEvent(); m_usCurrentProcID = (USHORT)GetCurrentProcessId(); m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0); if (m_sockRaw == INVALID_SOCKET) { std::cerr << "WSASocket() failed:" << WSAGetLastError() << std::endl; //10013 以一种访问权限不允许的方式做了一个访问套接字的尝试。 } else { WSAEventSelect(m_sockRaw, m_event, FD_READ); m_bIsInitSucc = TRUE; m_szICMPData = (char*)malloc(DEF_PACKET_SIZE + sizeof(ICMPHeader)); if (m_szICMPData == NULL) { m_bIsInitSucc = FALSE; } } } CPing::~CPing() { WSACleanup(); if (NULL != m_szICMPData) { free(m_szICMPData); m_szICMPData = NULL; } } BOOL CPing::Ping(DWORD dwDestIP, PingReply *pPingReply,DWORD dwBytes, DWORD dwTimeout) { return PingCore(dwDestIP, pPingReply, dwTimeout, dwBytes); } BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply,DWORD dwBytes, DWORD dwTimeout) { if (NULL != szDestIP) { return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout, dwBytes); } return FALSE; } BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout, DWORD dwBytes) { //判断初始化是否成功 if (!m_bIsInitSucc) { return FALSE; } //配置SOCKET sockaddr_in sockaddrDest; sockaddrDest.sin_family = AF_INET; sockaddrDest.sin_addr.s_addr = dwDestIP; int nSockaddrDestSize = sizeof(sockaddrDest); //构建ICMP包 //int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader); int nICMPDataSize = dwBytes + sizeof(ICMPHeader); ULONG ulSendTimestamp = GetTickCountCalibrate(); USHORT usSeq = ++s_usPacketSeq; memset(m_szICMPData, 0, nICMPDataSize); ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData; pICMPHeader->m_byType = ECHO_REQUEST; pICMPHeader->m_byCode = 0; pICMPHeader->m_usID = m_usCurrentProcID; pICMPHeader->m_usSeq = usSeq; pICMPHeader->m_ulTimeStamp = ulSendTimestamp; pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize); //发送ICMP报文 if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR) { return FALSE; } //判断是否需要接收相应报文 if (pPingReply == NULL) { return TRUE; } char recvbuf[65536] = { "