直接对网卡编程以实现网络数据的拦截与监控是件很复杂的事情。本文介绍使用“IP助手库函数”(iphlpapi.dll)轻松获取网络流量图的方法,并给出了具体实例程序。
实例程序的执行情况见下图所示:
从图中可以看到,用“IP助手库函数”可获取当前所有的网络连接情况,其中包括使用网卡的局域网连接,以及使用ISDN或调制解调器的拨号网络连接。可获取的信息包括:连接速度、界面类型、操作状态、当前总共收到和发送的字节数,等等。
其中“总共收到和发送的字节数”等信息完全是累计的。也就是说,这些信息不受网络连接断开的影响(如拨号网络),能完整记录各网络全天的吞吐总量。
定时扫描网络的最新吞吐量,并与上一时段的吞吐量做比较,即可制作网络流量图。上图所示的是拨号网络约六分钟的下载流量图,其中数据每秒刷新一次(X方向),网格单位是KB/每秒(Y方向)。
一、“IP助手库函数”的使用
用微软的“IP助手库函数”(iphlpapi.dll)可获取大量有关网络连接的有用信息。其中有关吞吐量的函数包括GetIfTable等,其定义为:
Private Declare Function GetIfTable Lib "iphlpapi" (ByRef pIfTable As Any, _ByRef pdwSize As Long, ByVal bOrder As Long) As Long
该函数的第一个参数指向一个缓冲区,函数执行后该缓冲区内被填入各网络连接的最新数据。缓冲区的结构是:
网络连接总数+网络连接1结构数据+网络连接2结构数据+...
其中“网络连接总数”占4个字节;每个“网络连接数据”的结构为:
Private Type MIB_IFROW
wszName(0 To 511) As Byte
dwIndex As Long '编号
dwType As Long '界面类型
dwMtu As Long '最大传输单元
dwSpeed As Long '界面速度
dwPhysAddrLen As Long '物理地址部分有效长度
bPhysAddr(0 To 7) As Byte '物理地址
dwAdminStatus As Long '管理状态
dwOperStatus As Long '操作状态
dwLastChange As Long '操作状态最近更新时间
dwInOctets As Long '总共收到(字节)
dwInUcastPkts As Long '总共收到(unicast包)
dwInNUcastPkts As Long '总共收到(non-unicast包)
dwInDiscards As Long '丢弃包总数(收到)
dwInErrors As Long '出错包总数(收到)
dwInUnknownProtos As Long '其它包总数(收到)
dwOutOctets As Long '总共发送(字节)
dwOutUcastPkts As Long '总共发送(unicast包)
dwOutNUcastPkts As Long '总共发送(non-unicast包)
dwOutDiscards As Long '丢弃包总数(发送)
dwOutErrors As Long '出错包总数(发送)
dwOutQLen As Long '发送队列长度
dwDescrLen As Long '界面描述部分有效长度
bDescr(0 To 255) As Byte '界面描述
End Type
需要指出的是,上述GetIfTable函数只能在Windows 98/2000/NT4以及部分Win95上工作。
二、实例程序(VB6)
' 用“IP助手”获取网络流量图
Option Explicit
Dim IfTable As MIB_IFROW ' 定义一个上述结构的变量
Dim buf() As Byte ' 缓冲区
Dim buf_size As Long ' 缓冲区实际大小
Dim rows As Long ' 当前网络连接总数
Dim i, j As Long
Dim Pic_X, Pic_Y, Old_In As Long ' 用于在绘制流量图中保存上一时段的有关值
'
Private Const ERROR_NOT_SUPPORTED = 50&
Private Const ERROR_SUCCESS = 0&
Private Declare Function GetIfTable Lib "iphlpapi" (ByRef pIfTable As Any, _
ByRef pdwSize As Long, ByVal bOrder As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef _
pDest As Any, ByRef pSource As Any, ByVal Length As Long)
Private Sub Form_Load()
i = GetIfTable(ByVal 0&, buf_size, 0)
If i = ERROR_NOT_SUPPORTED Then
MsgBox "函数GetIfTable只能在Win98/NT4/2000上工作。"
End
End If
ReDim buf(0 To buf_size - 1) As Byte ' 根据返回值,动态申请缓冲区
i = GetIfTable(buf(0), buf_size, True) '“True”的含义是“排序”
If i <> ERROR_SUCCESS Then End
Timer1.Interval = 1000 ' 刷新间隔定为一秒
Timer1.Enabled = True ' 启动记时器
Picture1.DrawMode = 13
Picture1.AutoRedraw = True ' 启动自动重画功能以防止画面丢失
Picture1.ScaleMode = 3 ' 设定画笔单位为象素(Pixel)
Pic_X = Picture1.ScaleWidth
End Sub
Private Function GetType(Type1 As Long) As String ' “界面类型”定义函数
Select Case Type1
Case 1: GetType = "Other"
Case 6: GetType = "Ethernet"
Case 9: GetType = "Tokenring"
Case 15: GetType = "FDDI"
Case 23: GetType = "PPP"
Case 24: GetType = "Loopback"
Case 28: GetType = "Slip"
End Select
End Function
Private Function GetState(State1 As Long) As String ' “操作状态”定义函数
Select Case State1
Case 0: GetState = "Not operational"
Case 1: GetState = "Operational"
Case 2: GetState = "Disconnected"
Case 3: GetState = "Connecting"
Case 4: GetState = "Connected"
Case 5: GetState = "Unreachable"
Private Sub Timer1_Timer()
ReDim buf(0 To buf_size - 1) As Byte
i = GetIfTable(buf(0), buf_size, True)
CopyMemory rows, buf(0), 4 ' 缓冲区的前四个字节是“网络连接总数”
For j = 1 To rows
CopyMemory IfTable, buf(4 + (j - 1) * Len(IfTable)), Len(IfTable)
有效编号(j - 1).Caption = Str(j)
界面类型(j - 1).Caption = GetType(IfTable.dwType)
连接速度(j - 1).Caption = IfTable.dwSpeed
总共收到(j - 1).Caption = Str(IfTable.dwInOctets)
If IfTable.dwSpeed = 9600 Then ' 绘制拨号网络的下载流量图
Pic_X = Pic_X + 1
If Pic_X > Picture1.ScaleWidth Then
Pic_X = 1
Picture1.Cls
For i = 1 To 8 ' 绘制网格
Picture1.Line (0, Picture1.ScaleHeight - i * 10 - 1)- _
(Picture1.ScaleWidth, Picture1.ScaleHeight - i * 10 - 1), &H808080
Next i
If Old_In = 0 Then
Old_In = IfTable.dwInOctets
Pic_Y = Picture1.ScaleHeight - 1
i = Picture1.ScaleHeight - (IfTable.dwInOctets - Old_In) / 102.4 - 1
Picture1.Line (Pic_X - 1, Pic_Y)-(Pic_X, i), &HFF& ' 绘制流量
Pic_Y = i
总共发送(j - 1).Caption = Str(IfTable.dwOutOctets)
操作状态(j - 1).Caption = GetState(IfTable.dwOperStatus)
总共错收(j - 1).Caption = Str(IfTable.dwInErrors)
总共错发(j - 1).Caption = Str(IfTable.dwOutErrors)
其它共收(j - 1).Caption = Str(IfTable.dwInUnknownProtos)
Next j
posted on 2009-08-12 14:12 青蛙學堂 阅读(433) 评论(0) 编辑 收藏 引用 所属分类: 硬件百科 、軟件布袋
Powered by: IT博客 Copyright © 青蛙學堂