I am trying to build an embedded device that would be connected to a router.
But I want to be able to know if the device is connected to the router or not using a PC or Mobile.
For example:
How can the PC detect if the google chromecast is connected on the same network or not ?
Do I need to communicate with each IP in the network on a specific port to ask ?
Or do I need to let the embedded device broadcast some information every N seconds ?
Thanks,
In any case you should consider doing a Gratuitous ARP on your embedded device. A gratuitous ARP will announce to all of the devices on your LAN that a new device has joined so they can update their ARP cache.
As far as a PC/Mobile device discovering your embedded device goes, you have a few options:
Option 1
If we can assume that this is a typical flat home network where all of the devices are on a single subnet and there is one gateway router * then you can give your embedded device a unique OUI. If you intend to sell this device you will need to apply for an OUI with the IEEE anyway unless whoever made your chipset supplies it with a MAC address already. Your PC/Mobile app can periodically check its ARP cache for an OUI that matches the unique OUI that you expect.
This will not work if the network is not flat and there are multiple routed subnets or VLANS. Here is a possible scenario: Lets suppose your embedded device connects to a client bridge range extender. If your PC/Mobile app is on the main access point it will never see the MAC address of the embedded device - instead it will see the MAC address of the client bridge. Multiple IPs will be mapped to the client bridge because the client bridge and the client bridge will be switching packets.
*I put the term router in italics because most home routers are merely doing NAT between the WAN/LAN and the LAN side of the router operates like a layer 2 switch.
Option 2
You can do a broadcast ping request, eg. ping xxx.xxx.xxx.255. You'll get a response back from all devices that will accept a broadcast ping request. Just make sure your device does. Then once you have a list of IP addresses you can attempt to open a TCP socket over the arbitrary port of your choosing with all of those IP addresses and then send some unique handshake packet. Your embedded device should be listening over this port and should have some unique reply to this unique packet. Most of the devices on the lan should generally not allow this socket to open, but if they do they should not understand the unique handshake message you send.
Option 3
Send a broadcast UDP datagram with some unique handshake payload. Then your embedded device should reply to the sender of this broadcast UDP packet with some unique response. After this response has been received by your PC/Mobile app you can then open a TCP socket with the IP address the response came from.
Related
I created a UDP server on android app, and this UDP server is reachable via wifi (Local network). I can receive and send data. However when I change to 4G network. The UDP server on Android not able to receive anything. I use ip chicken to check my cell phone IP address and my UDP server port is 2004. Is there anything wrong? or my public ip is not correct?
Assuming that your phone IP address is correct, and it looks like you have checks this, it is important to know that mobile network providers may not support UDP inbound connections on their networks.
While it's not true to say that all don't, it is true to say that not all do so if you want your solution to be portable across networks you may need to look at alternatives anyway.
There are examples and guides on traversing network address translation boundaries on networks - one good example, which is looking at peer to peer applications, is here: http://bford.info/pub/net/p2pnat/
This question already has answers here:
How to scan IP and Mac address of all Device Connected to wifi in android accurately?
(2 answers)
Closed 4 years ago.
I have a iOT device , i know the Mac address of the device .
My iOT device is connected to my wifi , i want to know is there any way to know the local ip of that device using it's mac address ? My requirement is to connect the android app to same wifi search for the device's ip address using Mac address and establish TCP connection .
Till now i have searched regarding this , i didn't get the perfect answer for this , ssdp scanning is really required for this or is there any other way to do this .
is RARP possible in android ?
please help me .
Two, maybe three, possible solutions that I know of:
Option 1: Ping the broadcast address, then read the ARP table
This assume you can't run any special code on the remote device you are trying to discover the IP address for, but it does have an ICMP stack that is enbled. (i.e. you can ping it)
Assuming this device supports ICMP (ping). You can send one or more ICMP ping requests to the broadcast address of your subnet and listen for responses back from all devices on the subnet. Then consult the local ARP table to see which device messages you back. You can try this from the command line of any computer. Let's say your local ip is 192.168.1.2 and your subnet mask is 255.255.255.0. It follows that your subnet's broadcast IP is 192.168.1.255. Therefore you can do this at the command prompt (Linux, Windows, Mac)
$> ping 192.168.1.255 // let this run for a few seconds, then cancel after it retries a few times
$> arp -a // this will dump the local ARP table of every MAC to IP mapping discovered and cached
It would take a little work to write the equivalent Android code to do this, but it should be possible. You may need to use the NDK to get to the lower level socket functions to read the arp table. You might be able to get the source ethernet via recvmsg.
Option 2: UDP broadcast.
This assumes you can run some sort of code on the remote device that it can respond to. It just listens on a designated port (e.g. UDP port 29999). Similar to above, the finder Android device just sends a broadcast UDP message to the broadcast address of the subnet mask. The payload of this message is just your own protocol to ask "who has 88-66-aa-6c-d5-c1" ? The device responds with something to the effect of "I have 88-66-aa-6c-d5-c1". The IP comes back as the "from" address in the socket recvfrom call. You could also build it into the protocol payload as well.
Option 3: It's been a while, but here's some hints.
I recall back when I worked on a hardware product with wifi, we were going to do some sort of auto-config protocol where the target device might not even be on the intended wifi, but we wanted to send some sort of message to it. We had experimented with some mix of broadcast UDP to 255.255.255.255 and sending a UDP packet to a multicast address between devices. I think when you broadcast to 255.255.255.255 or use multicast, it hits all devices as long as they are on the same physical segment or share an AP. Some experimentation required. You might be able to combine this approach with either option 1 or 2 above.
I have been trying to set up an app that allows communication between two devices, a server and a client. I have established the connection and can send messages between the two as long as they are connected to the same source of internet. When I connect the devices to two different sources, I am not able to establish a connection between the two. It works by entering the IP address of the server you want to connect to.
For example, if my server device is connected to my home Wi-Fi and my client device is connected to the same Wi-Fi router, communication works as supposed to. But, when I connect the server to Wi-Fi and my client to cellular data (or different Wi-Fi router), the client is not able to find the server.
From all the searching I've done, I found that it is because my server is bound to my local host. So my question is, How can I make my server reachable from anywhere regardless of what network you are connected to?
I used this tutorial to get my server running:
http://android-er.blogspot.com/2014/02/android-sercerclient-example-server.html
The very first comment is a question that asks why it only works on a local network and someone answered saying you have to set up port forwarding on your router. From what I understand, this will work only if the server device is always connected to the same router. This will not be the case for my app. The server will have a new IP address as the device changes networks. I want this IP address to always be reachable no matter what network the server is connected to.
You will need to create a relay server. This would be set up using a java application on the PC and it would manage virtual "rooms" that then relay the messages to the clients. The computer you run your relay server off of will need port forwarding but the clients will not. Much of the code from that tutorial could be applied to this concept.
See: How to create a java Server that accepts client connections and then build a relay connection for a client pair
If your server is behind a firewall, you will not be able to reach it unless that port is open on the firewall. The only way to avoid this is to have a non-firewalled server.
I"m building a P2P wifi app that requires bidirectional communication between every connected device and a central "host" (I've already addressed the issue of forcing the host onto that device in particular).
I've run through the developer.android tutorials and gotten all I can from those, but my issue at the moment is that I can't seem to get the host's sockets to connect to the P2P client devices properly...
My application for my host side currently displays all of the phones that have "connected" to it (via the p2p connect command) and has the addresses of all of those devices displayed in a list view on screen. These addresses are shown as IPV6(I think) addresses and are usually identical to the device's hard-coded MAC addresses, with one hex pair value changed. Example: Device's MAC is AA:BB:CC:DD:EE:FF and host's address for that device shows as being AA:BB:CC:DD:EE:13 (or similar).
The client side at this point in the workflow is waiting for the server to send it a small packet via port 8000.
However, at this point, when I attempt to connect from the host to any client, it throws the exception "Host could not be resolved..." and lists the device's IP address I'm trying to connect to, which properly matches the expected address that is displayed on screen of the connected devices.
I believe my particular concern revolves around the following line of code:
socket.connect((new InetSocketAddress(device.deviceAddress, 8000)), 5000);
Where device is the WifiP2pDevice that we are trying to connect to. In particular, looking at the InetSocketAddress help page, it expects our "device address" to be in the form of a string of IPV4 or IPV6. Is android's P2P "Device Address" really IPV6? Or am I missing something else completely obvious?
EDIT: I have been properly informed that P2P addresses are not applicable in any shape or form to sockets. The only way P2P sockets can be done this way in Android is:
1. Clients get the IP address of the group owner/server from the Broadcast receiver's P2PInfo object.
2. All of the clients connect to the server's ip using sockets.
3. As the server receives connections, the server can get the ip addresses from the client devices via the socket that is created for each client.
4. Once both parties have each others' IP addresses, proper bidirectional communication can be achieved.
I want to have my app able to connect to other devices over the same wifi network and transfer some data, that is phone A and phone B have my app installed and are on the same network. I am able to connect two devices currently with one acting as server and the other being client but this is with a static IP reference to the server device. In the open world this IP will change of course so my problem is how do I get phone A to start up as a server device then have phone B see the server device on the network and connect to it. So the server device would accept this client connection and carry out the needed actions when the connection is made. Is this even possible?
I believe you would have A device listening on port number x, and the client version (device B) looking for that same port number x. This could be wrong.
This is a job for DNS. If you don't have a DNS server available you could invent a discovery protocol in which machine A periodically multicasts the IP & port on which it is listening.
Machine B joins the multicast group. Once machine B knows A's address and port it can open a socket using the code you already have.