【Excel(64bit) VBA】【Winsock API】ポート番号(u-short型)をVBAで扱う方法とその検証

EXCEL

ポート番号、winsockではu-short(16bit 符号なし整数 0 – 65535)で扱うことになっているが、VBA上では、u-shortが存在しない。

同じサイズのintegerを使うコードをよく見かけるが、どうもその理屈がわからなかったのでサンプルプログラムで検証してみた。

検証用サンプルプログラム

Option Explicit

'htons/ntohs API
Public Declare PtrSafe Function htons Lib "wsock32.dll" (ByVal hostshort As Long) As Integer
Public Declare PtrSafe Function ntohs Lib "wsock32.dll" (ByVal netshort As Long) As Integer
 
Sub test()

    Dim i As Long
    Dim Ulong As Long
    
    For i = 0 To 65535
        Call Check_Sub(i)
        DoEvents
    Next i

End Sub


Sub Check_Sub(ByVal PortNumber As Long)
    
    Dim u_short_PortNumber As Integer
    Dim PortNumberTmp As Long
    Dim NWOrder_u_short_PortNumber As Integer
    
    u_short_PortNumber = Convert_u_short_PortNumber(PortNumber)
    
    Debug.Print "プログラム上で扱いやすいLong型のポート番号(0~65535まで)      :" & PortNumber
    Debug.Print "u_short型にはめ込んだPortNumber                                :" & u_short_PortNumber
    Debug.Print "htons() ->  ntohs() 検証  引数はunsigned shrot(16bit)型"
    Debug.Print "htons()変換(ホストオーダー⇒ネットワークバイトオーダー)      :" & htons(u_short_PortNumber)
    Debug.Print "ntohs()変換戻し(ネットワークバイトオーダー⇒ホストオーダー)  :" & ntohs(htons(u_short_PortNumber))
    Debug.Print "可読用表示変換                                                 : " & u_short_PortNumberToLong(ntohs(htons(u_short_PortNumber)))
      
End Sub


'ポート番号をu_short(16bitの符号なし整数型)に変換したデータの可読用表示用変換
Function u_short_PortNumberToLong(ByVal u_short_PortNumber As Integer) As Long
    u_short_PortNumberToLong = 65535 And u_short_PortNumber
End Function

'
'ポート番号をu_short(16bitの符号なし整数型)に変換する。
'VBでは、16bitの型はIntegerになるが、符号あり整数ため、32767以上の整数値を代入するとオーバーフローする。
'そのためBitレベルで,Integer型にはめ込む
Function Convert_u_short_PortNumber(ByVal PortNumber As Long) As Integer
    Select Case PortNumber
        Case Is < 0&: Err.Raise "UnderFlow  PortNumber is 0 - 65535"
        Case 0 To 32767:  Convert_u_short_PortNumber = PortNumber
        Case 32768 To 65535: Convert_u_short_PortNumber = PortNumber - 65536
        Case Is > 65535: Err.Raise Number:=513, Description:="OverFlow PortNumber is 0 - 65535"

    End Select

End Function


検証結果

  • 外部IF等からプログラムレベル(例えば引数)でポート番号を扱うにはLong型(32bit)しかない。
  • Long型(32bit)では、そのままポート番号として使えない(htons/ntohsの引数の型にあわない)ためInteger型(16bit)を使わざるおえない。
  • ただしInteger型(16bit)は符号なし整数しかなく、符号なし(Unsigned)のバリエーションがない。
  • そのため、32767以上のポート番号をそのまま変数に代入できない、マイナス符号も計算したbitレベルのはめ込みが必要になる。              処理例:Convert_u_short_PortNumber
  • そして、無理にはめ込んだことで、ポート番号の指定値を見るための変換関数も必要になる。                             処理例:u_short_PortNumberToLong

他サイトのサンプルプログラムでも似たようなコードを見るので、皆さんいろいろ苦労(工夫)されているのだろう。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました