VB编写C/S程序,解决U盘泛滥问题
海粟/文
--------------------------------------------------------------------------------
《软件报》24期
【编程引子】
随着MP3/MP4播放器价格的平民化,学生们普遍把手中的零用钱,转化为了心仪的数码产品。然而,它们在推动校园信息化进程的同时,学生实践课上乱用MP3,也成为计算机房病毒泛滥的元凶,令教师们防不胜防。与其被动地管理,还不如主动出击,比如在学生机上动动手脚。禁用USB功能?不行,这会给以后的机房维护带来不便;思前想后,笔者想到了C/S监控模式,这对于VB而言可谓"小菜一碟"。
【编程分析】
程序的大致思路是在学生机上安装客户端,实时监控USB移动存储设备,当发现系统中出现此类设备时,"主动"向教师机(即服务器端)发送本机用户名,教师端就可以轻松锁定目标了!
在功能实现上,主要借助于Winsock控件,所以在设计时首先要手动添加此部件的引用。此外,在协议的选择上,Winsock控件全面支持TCP和UDP协议。前者适合于建立稳定的连接,要求有连接请求以及响应的信息传递,能够保证数据传输的有效性,这在大量数据传输的情况下比较适用;而后者,则属于无连接协议,消息可以自由地从一方传递到另一方,无须连接请求与明确的连接关系,非常适合传输少量数据的情况。对于本例而言,采用UDP协议则是不二的选择。
为了防止学生手动终止监控程序,要求客户端程序运行后不显示主窗体,且隐藏任务列表(但不隐藏程序进程),这在一定程度上起到了隐蔽效果,如果把进程名改为"SVGHOST"什么的,效果就更好了!此外,服务器端还要求有一些手动功能,比如保存日志、清空列表等。
【主要代码】
1.客户端(Client)程序
客户端程序界面中,只须一个Winsock控件和一个时钟控件即可,前者用于向服务器端发送数据,后者用来实现实时监测。在窗体加载事件中,完成控件初始化工作,主要代码如下:
Private Sub Form_Load()
If App.PrevInstance = True Then End '防止程序重复运行
With UDPClient
.Protocol = sckUDPProtocol '指定协议
.RemoteHost = "abc" '远程服务器计算机的名字,此名称根据具体情况而定
.RemotePort = 1002 '连接的端口号。
End With
Form1.Visible = False
App.TaskVisible = False '使程序不出现在任务列表中
Timer1.Interval = 2000 '每隔两秒检测一次
Timer1.Enabled = True
End Sub
其中,控件的"RemoteHost"属性应设置为服务器端计算机名称,远程端口也应与服务器端程序绑定的端口一致。一切就绪后,时钟控件便自动进入工作状态,监视系统中的可移动存储设备,Timer()事件的主要代码如下:
Private Sub Timer1_Timer()
............ ‘变量声明与赋初值
temp = GetLogicalDriveStrings(Len(AllDrives),AllDrives)
Do
pos = InStr(AllDrives,Chr$(0))
If pos <> 0 Then
UDiskDrive = Left(AllDrives,pos)
AllDrives = Mid(AllDrives,pos + 1)
DriveType = GetDriveType(UDiskDrive)
If DriveType = DRIVE_REMOVABLE Then
UDiskFound = True
Exit Do
End If
End If
Loop Until AllDrives = "" Or pos = 0 Or DriveType = DRIVE_REMOVABLE
If UDiskFound Then
LpBuf = Space(30)
r = GetComputerName(LpBuf,Len(LpBuf))
If r <> 0 Then
PCName = Trim(LpBuf)
PCName = Left$(PCName,Len(PCName) - 1) '获取准确的本地计算机名
End If
UDPClient.SendData PCName '如果不停止USB设备,则始终发送数据
End If
End Sub
上述程序中,为了监视USB存储设备,使用了Windows API函数GetLogicalDriveStrings和GetDriveType,前者用来获取当前系统中全部逻辑驱动器的盘符信息,后者用来测试指定盘符的类型。如果发现USB存储设备,则通过API函数GetComputerName取得本地计算机名,并通过Winsock控件发送至服务器端,只要不停止USB设备,则始终发送数据信息。
2.服务器端(Server)程序
服务器端程序界面,主要包括Winsock控件、一个列表框和一组功能按钮,列表框的功能是分条显示接收来的客户端信息(如图1)。在窗体加载事件中,除了要指定UDP通信协议外,还要绑定本地端口(如"1002"),代码如下:
Private Sub Form_Load()
UDPServer.Protocol = sckUDPProtocol
UDPServer.Bind 1002 '绑定到本地的端口。
End Sub
在客户端数据到达之后,程序中要对数据中包含的计算机名进行判断、筛选,以去除重复数据,并将处理结果附带上当前时间后显示在列表中,主要代码如下:
Private Sub UDPServer_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
UDPServer.GetData strData
For i = 1 To 200 '最多支持200台计算机
If strData <> PCName(i) Then '排除重复数据
If PCName(i) = "" Then
PCName(i) = strData
Exit For
End If
Else
Exit Sub
End If
Next i
List1.AddItem Now() & " 在计算机<" & strData & ">中发现可移动存储设备!"
End Sub
此外,在对日志记录进行保存时,本例中使用系统日期和时间作为文件名,但要提醒大家注意时间中的"冒号"不能作为文件名的组成部分,应予以置换处理(使用Replace函数),相关代码比较简单,不必细说。