65.9K
CodeProject 正在变化。 阅读更多。
Home

MonitorIPScanner

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (12投票s)

2007年4月24日

4分钟阅读

viewsIcon

59554

downloadIcon

5471

用于控制和监控系统功能的文章。

Screenshot - MonitorIPScanner.jpg

概述

"Monitor IP Scanner" 是一款用于监控系统资源并执行其基本功能的工具。它面向系统管理员和普通用户,用于监控和管理他们的网络。

Monitor IP Scanner 可用于监控:内存使用情况、IP 配置、包含 IP 统计信息的网络配置详细信息、路由表和 ARP 表信息。您还可以使用 IP 地址或域名检查网络计算机是否处于活动状态。您甚至可以通过建立客户端/服务器连接在网络上的计算机之间发送消息。因此,服务器将支持更多的客户端连接。这还将用于从同一网络上的其他 PC 获取信息。例如:获取路由表、IP 统计信息、其他计算机的 ARP 表信息,并通过使用显示在 TCP 路由表中的 IP 地址或用户定义的 IP 地址建立 TCP 连接,将这些信息显示在另一台计算机上——这些都是可能的。

Components

Monitor IP Scanner 支持以下一些主要功能:

  1. 主机配置
  2. IP 配置
  3. MonAdmin 配置
  4. 网络配置
  5. Ping 配置
  6. 发送消息

Monitor IP 及其组件的演练。

主机配置

这将显示您系统的相关信息,例如内存使用情况和主机名。内存使用情况详细信息,如:页面文件使用情况、虚拟内存使用情况和页面错误计数等,这些信息是通过从 NTDLL.Lib 文件导入的 "ZwQuerySystemInformation" API 检索的。此 API 用于获取 PC 当前所有正在运行的进程信息。检索到的全局结构包含内存使用情况信息。

typedef struct _VM_COUNTERS {
    SIZE_T        PeakVirtualSize;
    SIZE_T        VirtualSize;
    ULONG        PageFaultCount;
    SIZE_T        PeakWorkingSetSize;
    SIZE_T        WorkingSetSize;
    SIZE_T        QuotaPeakPagedPoolUsage;
    SIZE_T        QuotaPagedPoolUsage;
    SIZE_T        QuotaPeakNonPagedPoolUsage;
    SIZE_T        QuotaNonPagedPoolUsage;
    SIZE_T        PagefileUsage;
    SIZE_T        PeakPagefileUsage;
} VM_COUNTERS;

typedef struct _SYSTEM_THREAD_INFORMATION {
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG            WaitTime;
    PVOID            StartAddress;
    CLIENT_ID        ClientId;
    KPRIORITY        Priority;
    KPRIORITY        BasePriority;
    ULONG            ContextSwitchCount;
    LONG            State;
    LONG            WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG            NextEntryDelta;
    ULONG            ThreadCount;
    ULONG            Reserved1[6];
    LARGE_INTEGER   CreateTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   KernelTime;
    UNICODE_STRING  ProcessName;
    KPRIORITY        BasePriority;
    ULONG            ProcessId;
    ULONG            InheritedFromProcessId;
    ULONG            HandleCount;
    ULONG            Reserved2[2];
    VM_COUNTERS        VmCounters;
    IO_COUNTERS        IoCounters;
    SYSTEM_THREAD_INFORMATION  Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;

extern "C"
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
                         IN UINT SystemInformationClass,
                         IN OUT PVOID SystemInformation,
                         IN ULONG SystemInformationLength,
                         OUT PULONG ReturnLength OPTIONAL
                         );

在此面板的底部,有一个名为“系统信息...”的按钮,它会为您提供有关以下信息:您系统上可用的驱动器、处理器、处理器速度等。

...
if(GetSystemInfo(m_SysInfo))
{
    UINT Res = (UINT) ::ShellExecute(GetSafeHwnd(), _T("open"),
        m_SysInfo, NULL, NULL, SW_SHOWNORMAL);
    if( Res <= HINSTANCE_ERROR )
    {
        AfxMessageBox( _T( "Error Executing \"MsInfo32.exe\" !" ),
            MB_OK | MB_ICONEXCLAMATION );
    }
}
... 

IP 配置

这将显示您 PC 中所有可用的网卡/适配器卡的信息,包括本地 IP 地址、MAC 地址、子网掩码、默认网关以及为特定网卡/适配器卡配置的其他信息。这还将显示 DNS 和 DHCP 信息。

获取带有 IP 地址、MAC 地址、子网掩码和默认网关的适配器信息

...
PIP_ADAPTER_INFO pAdapter = NULL;
dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen);

DNS information is retrieved using...

PFIXED_INFO     pFixedInfo;
m_dwResult = GetNetworkParams((PFIXED_INFO)m_pBuffer,&m_ulSize);

MonAdmin 配置

在这里,您可以从任何同时运行 Monitor IP 的其他计算机获取协议统计信息、路由表和 ARP 表信息。您可以通过以下方式执行此操作:在 TCP 连接表中选择您想要获取信息的 IP 地址,然后选择要检索的信息类型,接着单击“检索信息”按钮。如果您要查找的 IP 不在 TCP 连接表中,则单击“其他 IP”按钮并手动输入。进度条完成后,信息将显示在“检索到的信息”框中。

Structure and API used to get TCP Connection Table
PMIB_TCPTABLE pTcpTable;
GetTcpTable(pTcpTable, &dwSize, TRUE)
...

网络配置

这将显示您网卡/适配器的网络活动,并显示自激活网卡/适配器以来已发送的字节数、已丢弃的字节数、错误的字节数以及包含单播数据包详细信息的字节数。它还显示路由表、协议统计信息和 ARP 表信息。

检索网络活动的 कोड...

MIB_IFTABLE *m_pTable;
pGetIfTable=(TGetIfTable)GetProcAddress(LoadLibrary
                                        ("Iphlpapi.dll"), "GetIfTable");
pGetNumberOfInterfaces=(TGetNumberOfInterfaces)GetProcAddress
(LoadLibrary("Iphlpapi.dll"),"GetNumberOfInterfaces");
m_pTable=NULL;
if (!pGetIfTable || !pGetNumberOfInterfaces)
{
    AfxMessageBox("Error loading Iphlpapi.dll");
    return;
}
ULONG uRetCode = pGetIfTable(m_pTable,&m_dwAdapters,TRUE);

m_pTable=new MIB_IFTABLE[m_dwAdapters];
pGetIfTable(m_pTable,&m_dwAdapters,TRUE);
...

// Code to retrieve Protocol Statistics information ...

MIB_IPSTATS     IPStats;
m_dwResult = GetIpStatistics(&IPStats);

// Code to retrieve Routing Table information ...

MIB_IPFORWARDROW    IPForwardRow;
m_dwResult = GetBestRoute(inet_addr(_T("207.219.70.31")), 0,
                          &IPForwardRow);
...

// Code to retrieve ARP Table information

PMIB_IPNETTABLE pMib = (PMIB_IPNETTABLE)
malloc(sizeof(MIB_IPNETTABLE)+sizeof(MIB_IPNETROW)*nSize);

DWORD dwRet = GetIpNetTable(pMib,&nSize,TRUE);
...

Ping 配置

这使得能够检查您与另一台计算机之间的连接是已建立还是已断开。用法基本上是不言自明的,但如果不是……您可以通过域名或 IP 地址进行 ping 操作,并且可以设置超时、TTL 和要发送的数据包数量。

Ping 配置代码...

...
HANDLE hIP = IcmpCreateFile();
IP_OPTION_INFORMATION OptionInfo;
OptionInfo.Ttl = PingOption.m_nTTL;
OptionInfo.Tos = PingOption.m_nTOS;
if (PingOption.m_bDontFragment)
OptionInfo.Flags = IP_FLAG_DF;

Set up the data which will be sent
unsigned char* pBuf = new unsigned
char[PingOption.m_wDataRequestSize];
memset(pBuf, 'S', PingOption.m_wDataRequestSize);

Do the actual Ping
DWORD dwReplySize = sizeof(ICMP_ECHO_REPLY) +
max(PingOption.m_wDataRequestSize, 8);
unsigned char* pReply = new unsigned char[dwReplySize];
ICMP_ECHO_REPLY* pEchoReply =
reinterpret_cast(pReply);

DWORD nRecvPackets = IcmpSendEcho(hIP, addr, pBuf,
                                  PingOption.m_wDataRequestSize, &OptionInfo, 
                                  pReply, dwReplySize, PingOption.m_dwTimeout);
...

发送消息

要发送消息,必须创建一个服务器供客户端连接。如果已创建服务器,则必须创建一个客户端并连接到服务器。无论哪种方式,连接后您最多可以与连接到该服务器的三个其他客户端进行通信。使用用户名是可选的。

以下是使用发送消息选项的说明:

  1. 通过输入端口号(请记住此端口号)创建服务器。
  2. 按“启动服务器”按钮。
  3. 通过输入您创建的服务器的地址和端口号来创建客户端。
  4. 按“启动客户端”按钮。(注意:如果所有这些操作都在同一台计算机上进行,那么您唯一使用的地址将是环回地址 (127.0.0.1))。
  5. 一旦建立连接。将自动生成一个用户名,前缀为“Client #”,后跟连接号。
  6. 客户端窗口和服务器窗口将显示成功的问候语。
  7. 现在,可以通过单击“发送消息按钮”在客户端和服务器之间交换数据。
  8. 在每次从服务器发送消息之前,应从用户列表中选择要发送数据的客户端名称。

发送消息代码实现...

    {
        WORD wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD( 2, 2 );
        err = WSAStartup( wVersionRequested, &wsaData );
        ...
            Server_Addr.sin_port = htons(m_PortNo);
        Server_Addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
        Server_Addr.sin_family = AF_INET;
        addlen = sizeof(Server_Addr);
        Sock = socket(AF_INET, SOCK_STREAM, NULL);
        ...
            if(bind(Sock, (const sockaddr *) &Server_Addr, addlen))
                ...
                if(listen(Sock, 5))
                    ...
                    AfxBeginThread(&ServerThread, NULL, 0, 0, 0, NULL);
    }

    UINT ServerThread(LPVOID lpVoid)
    {
        m_Socket = accept(SendMsgDlg->Sock,(SOCKADDR *)
            &SendMsgDlg->Server_Addr, &SendMsgDlg->addlen);
        ...
            AfxBeginThread(&ServerThread, NULL, 0, 0, 0, NULL);
        ...
            while((Res = recv(m_Socket, RecvBuffer, sizeof(RecvBuffer),
                0)) != SOCKET_ERROR)
            {
                ...
            }
            send(m_Socket, "Disconnected", 100, 0);
            ...
                ::closesocket(m_Socket);
            ::AfxEndThread(0);
            return TRUE;
    } 
© . All rights reserved.