Option Explicit
Private Const RESOURCE_CONNECTED As Long = &H1&
Private Const RESOURCE_GLOBALNET As Long = &H2&
Private Const RESOURCE_REMEMBERED As Long = &H3&
Private Const RESOURCEDISPLAYTYPE_DIRECTORY& = &H9
Private Const RESOURCEDISPLAYTYPE_DOMAIN& = &H1
Private Const RESOURCEDISPLAYTYPE_FILE& = &H4
Private Const RESOURCEDISPLAYTYPE_GENERIC& = &H0
Private Const RESOURCEDISPLAYTYPE_GROUP& = &H5
Private Const RESOURCEDISPLAYTYPE_NETWORK& = &H6
Private Const RESOURCEDISPLAYTYPE_ROOT& = &H7
Private Const RESOURCEDISPLAYTYPE_SERVER& = &H2
Private Const RESOURCEDISPLAYTYPE_SHARE& = &H3
Private Const RESOURCEDISPLAYTYPE_SHAREADMIN& = &H8
Private Const RESOURCETYPE_ANY As Long = &H0&
Private Const RESOURCETYPE_DISK As Long = &H1&
Private Const RESOURCETYPE_PRINT As Long = &H2&
Private Const RESOURCETYPE_UNKNOWN As Long = &HFFFF&
Private Const RESOURCEUSAGE_ALL As Long = &H0&
Private Const RESOURCEUSAGE_CONNECTABLE As Long = &H1&
Private Const RESOURCEUSAGE_CONTAINER As Long = &H2&
Private Const RESOURCEUSAGE_RESERVED As Long = &H80000000
Private Const NO_ERROR = 0
Private Const ERROR_MORE_DATA = 234 'L // dderror
Private Const RESOURCE_ENUM_ALL As Long = &HFFFF
Private Type NETRESOURCE
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
pLocalName As Long
pRemoteName As Long
pComment As Long
pProvider As Long
End Type
Private Type NETRESOURCE_REAL
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
sLocalName As String
sRemoteName As String
sComment As String
sProvider As String
End Type
Private Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" (lpNetResource As NETRESOURCE, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Long) As Long
Private Declare Function WNetOpenEnum Lib "mpr.dll" Alias "WNetOpenEnumA" (ByVal dwScope As Long, ByVal dwType As Long, ByVal dwUsage As Long, lpNetResource As Any, lphEnum As Long) As Long
Private Declare Function WNetEnumResource Lib "mpr.dll" Alias "WNetEnumResourceA" (ByVal hEnum As Long, lpcCount As Long, lpBuffer As NETRESOURCE, lpBufferSize As Long) As Long
Private Declare Function WNetCloseEnum Lib "mpr.dll" (ByVal hEnum As Long) As Long
Private Declare Function VarPtrAny Lib "vb40032.dll" Alias "VarPtr" (lpObject As Any) As Long
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (lpTo As Any, lpFrom As Any, ByVal lLen As Long)
Private Declare Sub CopyMemByPtr Lib "kernel32" Alias "RtlMoveMemory" (ByVal lpTo As Long, ByVal lpFrom As Long, ByVal lLen As Long)
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As Any) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Any) As Long
Private Sub Command1_Click()
Const MAX_RESOURCES = 256
Const NOT_A_CONTAINER = -1
Dim bFirstTime As Boolean
Dim lReturn As Long
Dim hEnum As Long
Dim lCount As Long
Dim lMin As Long
Dim lLength As Long
Dim l As Long
Dim lBufferSize As Long
Dim lLastIndex As Long
Dim uNetApi(0 To MAX_RESOURCES) As NETRESOURCE
Dim uNet() As NETRESOURCE_REAL
bFirstTime = True
Do
If bFirstTime Then
lReturn = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, RESOURCEUSAGE_ALL, ByVal 0&, hEnum)
bFirstTime = False
Else
If uNet(lLastIndex).dwUsage And RESOURCEUSAGE_CONTAINER Then
lReturn = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, RESOURCEUSAGE_ALL, uNet(lLastIndex), hEnum)
Else
lReturn = NOT_A_CONTAINER
hEnum = 0
End If
lLastIndex = lLastIndex + 1
End If
If lReturn = NO_ERROR Then
lCount = RESOURCE_ENUM_ALL
Do
lBufferSize = UBound(uNetApi) * Len(uNetApi(0)) / 2
lReturn = WNetEnumResource(hEnum, lCount, uNetApi(0), lBufferSize)
If lCount > 0 Then
ReDim Preserve uNet(0 To lMin + lCount - 1) As NETRESOURCE_REAL
For l = 0 To lCount - 1
'Each Resource will appear here as uNet(i)
uNet(lMin + l).dwScope = uNetApi(l).dwScope
uNet(lMin + l).dwType = uNetApi(l).dwType
uNet(lMin + l).dwDisplayType = uNetApi(l).dwDisplayType
uNet(lMin + l).dwUsage = uNetApi(l).dwUsage
If uNetApi(l).pLocalName Then
lLength = lstrlen(uNetApi(l).pLocalName)
uNet(lMin + l).sLocalName = Space$(lLength)
CopyMem ByVal uNet(lMin + l).sLocalName, ByVal uNetApi(l).pLocalName, lLength
End If
If uNetApi(l).pRemoteName Then
lLength = lstrlen(uNetApi(l).pRemoteName)
uNet(lMin + l).sRemoteName = Space$(lLength)
CopyMem ByVal uNet(lMin + l).sRemoteName, ByVal uNetApi(l).pRemoteName, lLength
End If
If uNetApi(l).pComment Then
lLength = lstrlen(uNetApi(l).pComment)
uNet(lMin + l).sComment = Space$(lLength)
CopyMem ByVal uNet(lMin + l).sComment, ByVal uNetApi(l).pComment, lLength
End If
If uNetApi(l).pProvider Then
lLength = lstrlen(uNetApi(l).pProvider)
uNet(lMin + l).sProvider = Space$(lLength)
CopyMem ByVal uNet(lMin + l).sProvider, ByVal uNetApi(l).pProvider, lLength
End If
Next l
End If
lMin = lMin + lCount
Loop While lReturn = ERROR_MORE_DATA
End If
If hEnum Then
l = WNetCloseEnum(hEnum)
End If
Loop While lLastIndex < lMin
If UBound(uNet) > 0 Then
For l = 0 To UBound(uNet)
Select Case uNet(l).dwDisplayType
Case RESOURCEDISPLAYTYPE_DIRECTORY&
Debug.Print "Directory...",
Case RESOURCEDISPLAYTYPE_DOMAIN
Debug.Print "Domain...",
Case RESOURCEDISPLAYTYPE_FILE
Debug.Print "File...",
Case RESOURCEDISPLAYTYPE_GENERIC
Debug.Print "Generic...",
Case RESOURCEDISPLAYTYPE_GROUP
Debug.Print "Group...",
Case RESOURCEDISPLAYTYPE_NETWORK&
Debug.Print "Network...",
Case RESOURCEDISPLAYTYPE_ROOT&
Debug.Print "Root...",
Case RESOURCEDISPLAYTYPE_SERVER
Debug.Print "Server...",
Case RESOURCEDISPLAYTYPE_SHARE
Debug.Print "Share...",
Case RESOURCEDISPLAYTYPE_SHAREADMIN&
Debug.Print "ShareAdmin...",
End Select
Debug.Print uNet(l).sRemoteName, uNet(l).sComment
Next l
End If
为窗体增加如下的代码。
Private Sub Form_Load()
'控件的名字为 udpPeerA
With udpPeerA
'重点:必须将 RemoteHost 的值
'修改为计算机的名字。
.RemoteHost= "PeerB"
.RemotePort = 1001 '连接的端口号。
.Bind 1002 '绑定到本地的端口。
End With
frmPeerB.Show '显示第二个窗体。
End Sub
Private Sub txtSend_Change()
'在键入文本时,立即将其发送出去。
udpPeerA.SendData txtSend.Text
End Sub
Private Sub udpPeerA_DataArrival _
(ByVal bytesTotal As Long)
Dim strData As String
udpPeerA.GetData strData
txtOutput.Text = strData
End Sub
在窗体中添加如下的代码。
Private Sub Form_Load()
'控件的名字为 udpPeerB。
With udpPeerB
'重点:必须将 RemoteHost 的值改为
'计算机的名字。
.RemoteHost= "PeerA"
.RemotePort = 1002 '要连接的端口。
.Bind 1001 '绑定到本地的端口上。
End With
End Sub
Private Sub txtSend_Change()
'在键入后立即发送文本。
udpPeerB.SendData txtSend.Text
End Sub
Private Sub udpPeerB_DataArrival _
(ByVal bytesTotal As Long)
Dim strData As String
udpPeerB.GetData strData
txtOutput.Text = strData
End Sub
为窗体添加如下的代码。
Private Sub Form_Load()
'将 LocalPort 属性设置为一个整数。
'然后调用 Listen 方法。
tcpServer.LocalPort = 1001
tcpServer.Listen
frmClient.Show '显示客户端的窗体。
End Sub
Private Sub tcpServer_ConnectionRequest _
(ByVal requestID As Long)
'检查控件的 State 属性是否为关闭的。
'如果不是,
'在接受新的连接之前先关闭此连接。
If tcpServer.State <> sckClosed Then _
tcpServer.Close
'接受具有 requestID 参数的
'连接。
tcpServer.Accept requestID
End Sub
Private Sub txtSendData_Change()
'名为 txtSendData 的 TextBox 控件中
'包含了要发送的数据。当用户往文本框中
'键入数据时,使用 SendData 方法
'发送输入的字符串。
tcpServer.SendData txtSendData.Text
End Sub
Private Sub tcpServer_DataArrival _
(ByVal bytesTotal As Long)
'为进入的数据声明一个变量。
'调用 GetData 方法,并将数据赋予名为 txtOutput
'的 TextBox 的 Text 属性。
Dim strData As String
tcpServer.GetData strData
txtOutput.Text = strData
End Sub
Private Sub Form_Load()
'Winsock 控件的名字为 tcpClient。
'注意:要指定远程主机,可以使用
' IP 地址(例如:"121.111.1.1"),也可以使用
'计算机的“好听的名字”如下所示。
tcpClient.RemoteHost = "RemoteComputerName"
tcpClient.RemotePort = 1001
End Sub
Private Sub cmdConnect_Click()
'调用 Connect 方法,初始化连接。
tcpClient.Connect
End Sub
Private Sub txtSendData_Change()
tcpClient.SendData txtSend.Text
End Sub
Private Sub tcpClient_DataArrival _
(ByVal bytesTotal As Long)
Dim strData As String
tcpClient.GetData strData
txtOutput.Text = strData
End Sub
Private Sub Form_Load()
intMax = 0
sckServer(0).LocalPort = 1001
sckServer(0).Listen
End Sub
Private Sub sckServer_ConnectionRequest _
(Index As Integer, ByVal requestID As Long)
If Index = 0 Then
intMax = intMax + 1
Load sckServer(intMax)
sckServer(intMax).LocalPort = 0
sckServer(intMax).Accept requestID
Load txtData(intMax)
End If
End Sub