计算机网络作业

题目:可视化界面实现ping的功能


界面设计
界面


ping按键的事件

void CMFCApplication2Dlg::OnBnClickedButton1()
    {
    // TODO: 在此添加控件通知处理程序代码
    UpdateData(TRUE);
        CPing objPing;
        PingReply reply;
        CString str1,str2,str3,temp;
        int j = 0;
        m_ip.GetWindowText(str1);//获取edit中的内容。
        m_count.GetWindowText(str3);
        i = _ttoi(str3);
        //CString--》char*
        int len = WideCharToMultiByte(CP_ACP, 0, str1, -1, NULL, 0, NULL, NULL);
        char* szDestIP = new char[len + 1]; ;
        WideCharToMultiByte(CP_ACP, 0, str1, -1, szDestIP, len, NULL, NULL);

        while (j<i) {
            objPing.Ping(szDestIP, &reply);//ping

            str2 += "Reply from ";
            //temp.Format(_T("%s"), szDestIP);
            str2 += str1;
            str2 += ":  bytes=";
            temp.Format(_T("%d"), reply.m_dwBytes);
            str2 += temp;
            str2 += "  time=";
            temp.Format(_T("%d"), reply.m_dwRoundTripTime);
            str2 += temp;
            str2 += "ms  TTL=";
            temp.Format(_T("%d"), reply.m_dwTTL);
            str2 += temp;
            str2 += "\r\n";

            m_show.SetWindowTextW(str2);
            UpdateData(FALSE);
            j++;
            //Sleep(500);
        }
    }

ping.h

#pragma once

//在默认windows.h会包含winsock.h,当你包含winsock2.h就会冲突,因此在包含windows.h前需要定义一个宏,#define WIN32_LEAN_AND_MEAN ;去除winsock.h
//要么将#include <winsock2.h>放在#include<windows.h>前面或者直接去掉#include<windows.h>
#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib, "WS2_32")    // 链接到WS2_32.lib

#define DEF_PACKET_SIZE 32
#define ECHO_REQUEST 8
#define ECHO_REPLY 0

struct IPHeader
{
    BYTE m_byVerHLen; //4位版本+4位首部长度
    BYTE m_byTOS; //服务类型
    USHORT m_usTotalLen; //总长度
    USHORT m_usID; //标识
    USHORT m_usFlagFragOffset; //3位标志+13位片偏移
    BYTE m_byTTL; //TTL
    BYTE m_byProtocol; //协议
    USHORT m_usHChecksum; //首部检验和
    ULONG m_ulSrcIP; //源IP地址
    ULONG m_ulDestIP; //目的IP地址
};

struct ICMPHeader
{
    BYTE m_byType; //类型
    BYTE m_byCode; //代码
    USHORT m_usChecksum; //检验和 
    USHORT m_usID; //标识符
    USHORT m_usSeq; //序号
    ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部)
};

struct PingReply
{
    USHORT m_usSeq;
    DWORD m_dwRoundTripTime;
    DWORD m_dwBytes;
    DWORD m_dwTTL;
};

class CPing
{
public:
    CPing();
    ~CPing();
    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);
    ULONG GetTickCountCalibrate();
private:
    SOCKET m_sockRaw;
    WSAEVENT m_event;
    USHORT m_usCurrentProcID;
    char *m_szICMPData;
    BOOL m_bIsInitSucc;
private:
    static USHORT s_usPacketSeq;
};

ping.cpp

#include "stdafx.h"
#include "ping.h"
#include <iostream>
USHORT CPing::s_usPacketSeq = 0;

CPing::CPing() :m_szICMPData(NULL), m_bIsInitSucc(FALSE)
{
    WSADATA WSAData;
    //WSAStartup(MAKEWORD(2, 2), &WSAData);
    if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
    {
        /*如果初始化不成功则报错,GetLastError()返回发生的错误信息*/
        printf("WSAStartup() failed: %d\n", GetLastError());
        return;
    }
    m_event = WSACreateEvent();
    m_usCurrentProcID = (USHORT)GetCurrentProcessId();
    //setsockopt(m_sockRaw);
    /*if ((m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0)) != SOCKET_ERROR)
    {
    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;
    }
    }*/
    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 dwTimeout)
{
    return PingCore(dwDestIP, pPingReply, dwTimeout);
}

BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
    if (NULL != szDestIP)
    {
        return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout);
    }
    return FALSE;
}

BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
    //判断初始化是否成功
    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);
    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[256] = { "\0" };
    while (TRUE)
    {
        //接收响应报文
        if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)
        {
            WSANETWORKEVENTS netEvent;
            WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent);

            if (netEvent.lNetworkEvents & FD_READ)
            {
                ULONG nRecvTimestamp = GetTickCountCalibrate();
                int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize);
                if (nPacketSize != SOCKET_ERROR)
                {
                    IPHeader *pIPHeader = (IPHeader*)recvbuf;
                    USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4);
                    ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen);

                    if (pICMPHeader->m_usID == m_usCurrentProcID //是当前进程发出的报文
                        && pICMPHeader->m_byType == ECHO_REPLY //是ICMP响应报文
                        && pICMPHeader->m_usSeq == usSeq //是本次请求报文的响应报文
                        )
                    {
                        pPingReply->m_usSeq = usSeq;
                        pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp;
                        pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader);
                        pPingReply->m_dwTTL = pIPHeader->m_byTTL;
                        return TRUE;
                    }
                }
            }
        }
        //超时
        if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout)
        {
            return FALSE;
        }
    }
}

USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize)
{
    unsigned long ulCheckSum = 0;
    while (nSize > 1)
    {
        ulCheckSum += *pBuffer++;
        nSize -= sizeof(USHORT);
    }
    if (nSize)
    {
        ulCheckSum += *(UCHAR*)pBuffer;
    }

    ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);
    ulCheckSum += (ulCheckSum >> 16);

    return (USHORT)(~ulCheckSum);
}

ULONG CPing::GetTickCountCalibrate()
{
    static ULONG s_ulFirstCallTick = 0;
    static LONGLONG s_ullFirstCallTickMS = 0;

    SYSTEMTIME systemtime;
    FILETIME filetime;
    GetLocalTime(&systemtime);
    SystemTimeToFileTime(&systemtime, &filetime);
    LARGE_INTEGER liCurrentTime;
    liCurrentTime.HighPart = filetime.dwHighDateTime;
    liCurrentTime.LowPart = filetime.dwLowDateTime;
    LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;

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

    return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);
}

演示
这里写图片描述

说明

1.程序没有DNS解析,所有只能输入ip地址执行ping。
2.次数是指ping的次数。
3.程序没有做错误处理,输入不合理可能导致程序崩溃强退。


参考

http://www.cnblogs.com/goagent/p/4078940.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值