【发布时间】:2017-04-04 14:30:57
【问题描述】:
我创建了下面的 Excel VBA 代码,它使用 Winsock API 连接到 IP 地址,从 Excel 单元格发送文本字符串并接收文本字符串作为回报。
我的代码最初指向 IP 地址 127.0.0.1,端口为 80,没有任何问题。但是,此后我不得不将目标端口更新为60401,这还需要将端口输入变量sin_port 更改为Long,因为新端口超过了VBA 整数的最大长度。在这些更新之后,代码仍然可以编译,但是 Winsock API 没有处理任何东西??
我认为该错误可能与sin_zero 变量有关,该变量可能会随着端口长度的增加缓冲过多的零?我试过调整这个变量并在别处诊断代码,但在修改代码几个小时后它仍然没有处理。
非常感谢所有帮助。谢谢。
原始代码 - 端口 80 - 编译和处理成功
Type WSAData
wVersion As Integer
wHighVersion As Integer
szDescription(0 To 255) As Byte
szSystemStatus(0 To 128) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Type sockaddr_in
sin_family As Integer
sin_port As Integer
sin_addr As Long
sin_zero(0 to 7) As Byte
End Type
Public Declare Function WSAStartup Lib "ws2_32" ( _
ByVal wVersionRequired As Integer, ByRef lpWSAData As WSAData) As Long
Public Declare Function WSAGetLastError Lib "ws2_32" () As Long
Public Declare Function socket Lib "ws2_32" ( _
ByVal af As Long, ByVal socktype As Long, ByVal protocol As Long) As Long
Public Declare Function connect Lib "ws2_32" ( _
ByVal sock As Long, ByRef name As sockaddr_in, ByVal namelen As Integer) As Long
Public Declare Function send Lib "ws2_32" ( _
ByVal sock As Long, ByVal buf As String, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function recv Lib "ws2_32" ( _
ByVal sock As Long, ByRef buf As Byte, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function inet_addr Lib "ws2_32" ( _
ByVal s As String) As Long
Public Declare Function htons Lib "ws2_32" ( _
ByVal hostshort As Long) As Long
Function FetchData() As String
Dim iReturn As Long
Dim wsaDat As WSAData
iReturn = WSAStartup(&H202, wsaDat)
If iReturn <> 0 Then
MsgBox "WSAStartup failed", 0, ""
End If
Dim sock As Long
Dim sock1 As Long
Dim lasterr As Long
Dim i As Long
Dim buf(10) As Byte
Dim s As String
Dim j As Integer
sock = socket(2, 1, 6)
Dim addr As sockaddr_in
addr.sin_family = 2
addr.sin_port = htons(80)
addr.sin_addr = inet_addr("127.0.0.1")
i = connect(sock, addr, LenB(addr))
i = send(sock, "*SRTF" & vbCr, 6, 0)
i = recv(sock, buf(0), 10, 0)
For j = 0 To i - 1
s = s & Chr(buf(j))
Next
FetchData = s
End Function
Sub Button2_Click()
Range("C3").Formula = FetchData()
End Sub
新代码 - 端口 60401 - 编译但不处理?
Type WSAData
wVersion As Integer
wHighVersion As Integer
szDescription(0 To 255) As Byte
szSystemStatus(0 To 128) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type
Type sockaddr_in
sin_family As Integer
sin_port As Long
sin_addr As Long
sin_zero(0 to 7) As Byte
End Type
Public Declare Function WSAStartup Lib "ws2_32" ( _
ByVal wVersionRequired As Integer, ByRef lpWSAData As WSAData) As Long
Public Declare Function WSAGetLastError Lib "ws2_32" () As Long
Public Declare Function socket Lib "ws2_32" ( _
ByVal af As Long, ByVal socktype As Long, ByVal protocol As Long) As Long
Public Declare Function connect Lib "ws2_32" ( _
ByVal sock As Long, ByRef name As sockaddr_in, ByVal namelen As Integer) As Long
Public Declare Function send Lib "ws2_32" ( _
ByVal sock As Long, ByVal buf As String, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function recv Lib "ws2_32" ( _
ByVal sock As Long, ByRef buf As Byte, ByVal bufLen As Long, ByVal flags As Long) As Long
Public Declare Function inet_addr Lib "ws2_32" ( _
ByVal s As String) As Long
Public Declare Function htons Lib "ws2_32" ( _
ByVal hostshort As Long) As Long
Function FetchData() As String
Dim iReturn As Long
Dim wsaDat As WSAData
iReturn = WSAStartup(&H202, wsaDat)
If iReturn <> 0 Then
MsgBox "WSAStartup failed", 0, ""
End If
Dim sock As Long
Dim sock1 As Long
Dim lasterr As Long
Dim i As Long
Dim buf(10) As Byte
Dim s As String
Dim j As Integer
sock = socket(2, 1, 6)
Dim addr As sockaddr_in
addr.sin_family = 2
addr.sin_port = htons(60401)
addr.sin_addr = inet_addr("127.0.01")
i = connect(sock, addr, LenB(addr))
i = send(sock, "*SRTF" & vbCr, 6, 0)
i = recv(sock, buf(0), 10, 0)
For j = 0 To i - 1
s = s & Chr(buf(j))
Next
FetchData = s
End Function
Sub Button2_Click()
Range("C3").Formula = FetchData()
End Sub
【问题讨论】:
-
您无法更改这些结构中的类型。这些结构的全部意义在于它们是一个定义良好的二进制接口。将其改回整数。
-
你的 htons 也是错误的。它适用于 16 位类型。缺少无符号类型对您来说很不方便。您将需要更好地掌握二进制表示、字节序、二进制补码等。
-
@MajorCoder 您在哪里找到要添加到项目的参考?我在我的项目 PC(W7-64 位)上的任何地方都找不到它。
标签: vba excel sockets winapi winsock