计算机网络作业

来源:互联网 发布:鬼子来了被禁 知乎 编辑:程序博客网 时间:2024/06/03 09:24

题目:可视化界面实现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 0struct 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