2017-04-04 22 views
1

以下のExcel VBAコードを作成しました。これはWinsock APIを使用してIPアドレスに接続し、Excelセルからテキスト文字列を送信し、戻る。VBA Winsockが長いポート長(sin_port)で動作しない

私のコードは当初、ポート80のIPアドレス127.0.0.1を指していて問題はありませんでした。しかし、私は宛先ポートを60401に更新しなければならなかったので、新しいポートがVBA Integerの最大長を超えているため、ポート入力変数sin_portをLongに変更する必要がありました。これらの更新後、コードはコンパイルされますが、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 
+1

これらの構造体の型を変更することはできません。これらの構造体の全体的なポイントは、それらが明確に定義されたバイナリインタフェースであることです。それをIntegerに戻してください。 –

+0

あなたの息子も間違っています。 16ビットタイプで動作します。署名のない型の欠如はあなたにとって不便です。あなたは、バイナリ表現、エンディアン、2の補数などをもっとよく把握する必要があります。 –

+0

@ MajorCoderプロジェクトに追加する参照はどこで見つかりましたか?私は自分のプロジェクトPC(W7-64 Bit)のどこにも見つからない。 – Jaberwocky

答えて

1

あなたはsin_portフィールドのための大規模なデータ・タイプを使用するsockaddr_inのあなたの定義を変更します。あなたはそれをすることはできません。 Winsockとの互換性を維持するために、元の定義を復元する必要があります。

htons()の定義も間違っています。実際のhtons()の関数ws2_32は、定義したとおりに32ビットの数値ではなく16ビットの数値で動作します(htonl()は32ビットの数値で動作します)。

あなたに実行している本当の問題は、VBAのIntegerタイプがであるということです、それが保持できる最大値は、あなたがより高い値を使用しようとすると、それが負にラップします32767で、に署名しました。

のWinsockの実際sockaddr_in構造体(及びhtons()機能)sin_portフィールドの16ビット符号なしタイプを使用します。 VBAは単純に16ビットの符号なしタイプを持っていません。だから、あなたは16ビットのIntegerと署名して生きなければなりません。

はあなたの定義を修正する必要があります。

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 htons Lib "ws2_32" (_ ByVal hostshort As Integer) As Integer 

今、言われていることを、符号なし番号60401が進0xEBF1です。これはと同じ値で、 -5135という数字が付けられています。 htons()でスワップしたときに0xF1EB(-3605)になります。

ので、代わりにこれらのいずれかを試してみてください。

addr.sin_port = htons(&HEBF1) 

addr.sin_port = htons(-5135) 

addr.sin_port = -3605 

をさらに、inet_addr("127.0.01")inet_addr("127.0.0.1")をお読みください。

関連する問題