ポート番号、winsockではu-short(16bit 符号なし整数 0 – 65535)で扱うことになっているが、VBA上では、u-shortが存在しない。
同じサイズのintegerを使うコードをよく見かけるが、どうもその理屈がわからなかったのでサンプルプログラムで検証してみた。
検証用サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
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
他サイトのサンプルプログラムでも似たようなコードを見るので、皆さんいろいろ苦労(工夫)されているのだろう。
コメント