0

I have a wifi sensor module (SN8200 EVK) running a webserver. The board is configured to work as a STA and automatically join a WiFi router. The sensor board uses the Hostname: "sensor" and a DHCP interface to get its IP address.

I am developing a visual studio C# application to connect to this webserver. The application runs on a laptop which is connected to the same WiFi router.

Sensor Board <-----> WiFi Router <-----> Laptop

The application can connect to the sensor board if I use the board IP address. As the IP address is not static, I would like to use the Hostname to retrieve the IP.

I tried to use GetHostEntry but got an unknown host result.

IPHostEntry host;
host = Dns.GetHostEntry("sensor");

Something strange is that if I use GetHostEntry with the IP address it cannot resolved the hostname neither.

The GetHostEntry works fine if I try with the laptop hostname or IP. It looks like GetHostEntry cannot resolve the hostname behind the router.

Any help is welcome, Thanks.

leppie
  • 115,091
  • 17
  • 196
  • 297
Franck
  • 1
  • 2
  • 1
    If it is not in DNS or hosts file, it can't be resolved by name. Also the title is a bit misleading – Sami Kuhmonen May 18 '15 at 11:57
  • 2
    This mainly depends if the sensor board try to register itself in the DNS server or if it has to be done manually. A simple test, try `ping sensor` to see if your computer knows this hostname or not. If not, try adding sensor into your DNS Server or Hosts file. – Hybris95 May 18 '15 at 11:59
  • Can a WiFi router maintain a name-association with a dynamic (changing) IP address? – Tim May 18 '15 at 12:18
  • Why would it not Tim ? If each change is registered, I don't see why it would not maintain the DNS. – Hybris95 May 18 '15 at 12:21
  • @Tim Can it? absolutely. Does it? it depends on the router model. – Scott Chamberlain May 18 '15 at 13:35
  • @Hybris95 you are right, it looks like the board does not register itself in the DNS server and ping sensor does not work. And the WiFi module datasheet does not show anyway to get to register by itself :(. – Franck May 18 '15 at 14:23
  • Adding manually the sensor name and IP address to the DNS Server file works. But as the IP is dynamic, it may not work next time (or is there a trick here?). Thanks! – Franck May 18 '15 at 14:34
  • Maybe fix the IP ? By registering the Mac address to a specific IP ? (If it uses DHCP) – Hybris95 May 18 '15 at 15:04

1 Answers1

0

Static IP Solution

First :

Configure in your Wifi Router a fixed IP Address inside the DHCP Server.
PS : I'm pretty sure the Mac address is not dynamic

Second :

Add the hostname in your DNS Server with the previously fixed IP Address.

Scan the network for IPs and check Mac Address Solution

Before using the following code you will have to ping the whole range of IPs the sensor board can use in order to refresh your ARP Cache.

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Net;
using System.Collections.Generic;

namespace GetIpNetTable
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] ips = searchIpsFromMac("ff-ff-ff-ff-ff-ff");
            if (ips.Length != 0)
            {
                foreach (string ip in ips)
                {
                    // TODO - Do what you want with your IP address
                    Console.WriteLine(ip);
                }
            }
            Console.ReadKey();
        }

        // The max number of physical addresses.
        const int MAXLEN_PHYSADDR = 8;

        // Define the MIB_IPNETROW structure.
        [StructLayout(LayoutKind.Sequential)]
        struct MIB_IPNETROW
        {
            [MarshalAs(UnmanagedType.U4)]
            public int dwIndex;
            [MarshalAs(UnmanagedType.U4)]
            public int dwPhysAddrLen;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac0;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac1;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac2;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac3;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac4;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac5;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac6;
            [MarshalAs(UnmanagedType.U1)]
            public byte mac7;
            [MarshalAs(UnmanagedType.U4)]
            public int dwAddr;
            [MarshalAs(UnmanagedType.U4)]
            public int dwType;
        }

        // Declare the GetIpNetTable function.
        [DllImport("IpHlpApi.dll")]
        [return: MarshalAs(UnmanagedType.U4)]
        static extern int GetIpNetTable(
           IntPtr pIpNetTable,
           [MarshalAs(UnmanagedType.U4)]
         ref int pdwSize,
           bool bOrder);

        [DllImport("IpHlpApi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern int FreeMibTable(IntPtr plpNetTable);

        // The insufficient buffer error.
        const int ERROR_INSUFFICIENT_BUFFER = 122;

        static string[] searchIpsFromMac(string macSearched)
        {
            List<string> ips = new List<string>(1);

            // The number of bytes needed.
            int bytesNeeded = 0;

            // The result from the API call.
            int result = GetIpNetTable(IntPtr.Zero, ref bytesNeeded, false);

            // Call the function, expecting an insufficient buffer.
            if (result != ERROR_INSUFFICIENT_BUFFER)
            {
                // Throw an exception.
                throw new Win32Exception(result);
            }

            // Allocate the memory, do it in a try/finally block, to ensure
            // that it is released.
            IntPtr buffer = IntPtr.Zero;

            // Try/finally.
            try
            {
                // Allocate the memory.
                buffer = Marshal.AllocCoTaskMem(bytesNeeded);

                // Make the call again. If it did not succeed, then
                // raise an error.
                result = GetIpNetTable(buffer, ref bytesNeeded, false);

                // If the result is not 0 (no error), then throw an exception.
                if (result != 0)
                {
                    // Throw an exception.
                    throw new Win32Exception(result);
                }

                // Now we have the buffer, we have to marshal it. We can read
                // the first 4 bytes to get the length of the buffer.
                int entries = Marshal.ReadInt32(buffer);

                // Increment the memory pointer by the size of the int.
                IntPtr currentBuffer = new IntPtr(buffer.ToInt64() +
                   Marshal.SizeOf(typeof(int)));

                // Allocate an array of entries.
                MIB_IPNETROW[] table = new MIB_IPNETROW[entries];

                // Cycle through the entries.
                for (int index = 0; index < entries; index++)
                {
                    // Call PtrToStructure, getting the structure information.
                    table[index] = (MIB_IPNETROW)Marshal.PtrToStructure(new
                       IntPtr(currentBuffer.ToInt64() + (index *
                       Marshal.SizeOf(typeof(MIB_IPNETROW)))), typeof(MIB_IPNETROW));
                }

                for (int index = 0; index < entries; index++)
                {
                    MIB_IPNETROW row = table[index];
                    IPAddress ip = new IPAddress(BitConverter.GetBytes(row.dwAddr));
                    string macAddr = row.mac0.ToString("X2") + '-' +
                        row.mac1.ToString("X2") + '-' +
                        row.mac2.ToString("X2") + '-' +
                        row.mac3.ToString("X2") + '-' +
                        row.mac4.ToString("X2") + '-' +
                        row.mac5.ToString("X2");
                    if (macAddr.ToUpper() == macSearched.ToUpper())
                    {
                        ips.Add(ip.ToString());
                    }
                }
            }
            finally
            {
                // Release the memory.
                FreeMibTable(buffer);
            }
            return ips.ToArray();
        }
    }
}

References : https://stackoverflow.com/a/1148861/3635715

Community
  • 1
  • 1
Hybris95
  • 2,286
  • 2
  • 16
  • 33
  • yes if I fix the IP address I won't have any problem to find the sensor board. I won't even need the hostname to access the board. I want to avoid fixing the the IP address to make it easier for the customer as I won't be there to setup their network. I am a bit lost on how to keep the IP address dynamic and find this sensor board on the network. Is there a way to scan a range of IP addresses to find a device on the network (using hostname or other)? Sorry, I don't know much about networking... – Franck May 19 '15 at 15:31
  • A DNS Server fixes a name with an IP. If the IP changes, the DNS will just point to nothing. Since your sensor board does not communicate to the DNS Server. It will not inform that the IP has changed and will not register the new hostname/ip to the DNS Server. So you can't have a dynamic IP behaviour with a DNS without manually changing the DNS registry each time the IP changes. Which is why you need to fix the IP (or have something that scans regularly the network to check the new ip of this sensor board). – Hybris95 May 20 '15 at 09:02