Search code examples
javajna

Network byte order to host byte order conversion Java


I am using a windows-dll through jna for communicating with some dongle servers. The dll provides three functions, which are connect, disconnect and getting the connection status of the dongles. Connecting and disconnecting works. But when I query the status, the device should return an ip-address which i save into a DWORD. The code is something like, where DWORDByReference IpAddress is an out-parameter:

int AwUsbGetConnectionStatus(String Hub, DWORDByReference IpAddress, IntByReference Status, DWORD Timeout, HANDLE Event); DWORD value = ipAddress.getValue();

The specification of the dll states: "IpAddress is in host byte order and can be converted to TCP/IP network byte order using the WinSock htonl function."

In another thread i read that the java equivalent to htonl is:

static int htonl(int val) { return ByteBuffer.allocate(4).putInt(val) .order(ByteOrder.nativeOrder()).getInt(0); }

But the problem is, that i get weird values. But somehow they do correspond to the supposed value of the ip-addresses.
For example when the original Ip was: 192.168.102.118
it returns 1986439360
and when i convert it with the method above, it's -1062705546.
But i guess it should be 192168102118 when converted properly

Also another Ip-Address i tried was: 192.168.102.112 for which i get 1885776064 and when i convert that it's -106270552

So the difference between the Ip-Addresses is still 6 for the original Address and for the converted value. I tried this with different Ips and the difference between the Ips always matches the supposed values. So does anyone know, if there is something wrong with the way i convert the value the dll-function returns or could there even be a problem when i get the value of the DWORD parameter?


Solution

  • You should set the order before putting the little-endian address into it.

    And it appears (from your comment "i guess it should be 192168102118 when converted properly") that you want dotted-quad output; for that, using a byte array may be more natural:

    static byte[] htoip(int ipv4) {
      return ByteBuffer.wrap(new byte[4])
                       .order(ByteOrder.nativeOrder())
                       .putInt(ipv4)
                       .array();
    }
    

    This result is suitable for passing to InetAddress.getByAddress(), etc.

    While this isn't the simplest way to reverse 4 bytes, its use of ByteOrder.nativeOrder() makes it portable and future-proof.