I am trying to connect 2 devices through sockets, so that they can exchange data. They are also connected via wifi hotspot. I am using Services.
Device 1 is the hotspot (where the ServerSocket is implemented), Device 2 is the one who connects to it (where the Socket is implemented).
I did some research and i am able to get the ip of each one of them (but calculated on their own class). But in order for me to create the client socket, i need the IP Address of the host (the phone that is working as a hotspot) in the other class. I can not get it on the server side, because that part of the code wont be executed, since i am using one phone to create the hotspot network and another one to connect to it.
I know that usually the IP Address of a device that is tethering is generally the same, but i can not trust that, because i gotta make sure it works on all phones.
So, how can i get the ip address of the server (hotspot host) in the client (phone connected to that hotspot) service ?
In the client side you can use dhcp.gateway to get the server side(The one who created hotspot) ip address.
private final WifiManager manager;
private final DhcpInfo dhcp;
private InetAddress getServerIP() {
manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
dhcp = manager.getDhcpInfo();
final String address = Formatter.formatIpAddress(dhcp.gateway);// gateway -
default gateway IP address
InetAddress serverIP = null;
try {
serverIP = InetAddress.getByName(address);
if(mDebug)
Log.i("Server IP ","" + serverIP.toString());
} catch (Exception e) {
if(mDebug)
Log.e("Cannot find server's IP. Error ","" + e.toString());
}
return serverIP ;
}
Determine the ip of the gateway. Programmatically getting the gateway and subnet mask details. Use the WifiManager.getDhcpInfo().gateway
.
Related
I want the ability to specify and constrain the interface over which UDP datagrams will be sent.
I want to do this without physically disabling the "non wanted" interface. Assume standard INET connectivity is available over the chosen interface (in fact assume that if both interfaces are active then INET connectivity is available over boti)
Most mobile devices will send data over Wifi (in preference to Data interface) if the Wifi interface is enabled; but I want to know how to grammatically "force" UDP over my chosen interface.
There are similar questions already posted, but no question hits the topic precisely. Also I would like the programmed solution to be available (generically or via support library) as FAR BACK as possible in terms of Android SDK versions.
Please note that question "Android how to select wifi network interface to send udp packet" is old and was NEVER answered.
There is an issue with cyanide's answer - how does one ascertain the valid WiFi interface value associated with getName() for ALL devices, current and future?
The solution I have come up with would entail finding the IP address associated with the WiFi interface, then obtaining a UDP socket which is BOUND to this address. Getting a handle onto the WiFi interface can be done by accessing the WiFiManager:
WifiManager wifiManager =
(WifiManager) context.getApplicationContext ()
.getSystemService (Context.WIFI_SERVICE);
.....
int localInetAddressInt = wifiManager.getDhcpInfo ().ipAddress;
ByteBuffer tmp = ByteBuffer.allocate (4);
tmp.putInt (localInetAddressInt);
InetAddress localInetAddress = InetAddress.getByAddress (tmp.array ());
DatagramSocket socket = new DatagramSocket (portNumber, localInetAddress);
Then, when sending over the DatagramSocket (socket), the device SHOULD route the datagram over the appropriate interface, i.e. the interface associated with bound IP address, i.e. the WiFi interface to which the IP address is bound. The IP address would normally be associated with the WiFi interface by the WiFi Access Point via DHCP.
Use NetworkInterface.getNetworkInterfaces" to get list of all active interfaces.
Then for each interface use NetworkInterface.getName.For a wifi it will be wlanXX (Samsung and other), tiwlanXX (Motorola), ethXX (HTC) and e0 (Blackberry). With mobile net it most certainly be rmnetXX.
Then you can use NetworkInterface.getInetAddrress for creating socket.
When WiFi is unavailable, only rmnet appears. Similarly, when WiFi is available, rmnet will not appear, even if Mobile Data is enabled.
Added 30May17 In fact, I doubt that is possible to do what you intend, as it looks like the mobile network is automatically switched off when WiFi is available.
WifiManager wifiManager =
(WifiManager) context.getApplicationContext ()
.getSystemService (Context.WIFI_SERVICE);
.....
int localInetAddressInt = wifiManager.getDhcpInfo ().ipAddress;
ByteBuffer tmp = ByteBuffer.allocate (4);
tmp.putInt (localInetAddressInt);
byte swap; for(int i = 0; i < 2; i++) { swap = tmp.get(i); tmp.put(i, tmp.get(3 - i)); tmp.put(3 - i, swap); }
InetAddress localInetAddress = InetAddress.getByAddress (tmp.array ());
DatagramSocket socket = new DatagramSocket (portNumber, localInetAddress);
This worked for me!
EDIT:
Nope it doesn't. When Mobile data is ON, it doesn't go via WIFI
I'm creating a simple chat program that connects two android devices and they can send simple message
I run the server with Socket on a port (1234 for example)
The problem is from the client i do not know the server IP Address. (and i dont want to enter it manually)
is there a way to find a server that is running on a specific port?or can i run the server on some specific static IP that i can give it to clients?
if not is there another way to communicate with android devices that works on Android 2.2+(don't want to use wifi direct) ?
Thanks in Advance
You can broadcast a udp message from the server specifying your ip in the message. Let the client receive the broadcast and use that msg as the ip address to connect to the socket. (PS : The broadcast receiver must b allowed to receive broadcasts). And you are done!
Assign one SERVER predominantly for getting details such as IP ADDRESS, PORT number,etc.. from all the clients.
Each client when activated will contact the SERVER to register itself first and will get the details(IP ADDRESS,etc) of other device to communicate.
Now they can start waiting for specific device.
On 4.1 you can use Mutlicast DNS for service discovery via the NsdManager (if you are on the same network). If you need this to work over the Internet/3G there is really no good way to do it. You could use Google Cloud Messaging (GCM) to notify clients about the server address, but in any case you will need one 'real' server on a stable address that all participants can reach.
http://developer.android.com/reference/android/net/nsd/NsdManager.html
InetAddress.getLocalHost(); doesnot work for me but ya below code work for me
DhcpInfo dhcp = mWifiManager.getDhcpInfo();
int dhc = dhcp.serverAddress;
String dhcS = ( dhc & 0xFF)+ "."+((dhc >> 8 ) & 0xFF)+"."+((dhc >> 16 ) & 0xFF)+"."+((dhc >> 24 ) & 0xFF);
dhcS contains IP address of server,I used for Wireless connection between multiple devices.
You can use this code
connectionSocket.getRemoteSocketAddress();
No the port can never be fixed with a IP. It is always provided by the user. To know the IP address of the server automatically, you can run this program associated with the chat program.
public class Net {
public Net() throws UnknownHostException {
InetAddress ia = InetAddress.getLocalHost();
System.out.println(ia);
ia = InetAddress.getByName("local host");
System.out.println(ia);
}
public static void main(String args[]) throws UnknownHostException {
Net a = new Net();
}
}
You run can this program by the help of a button which is associated with your chat program.
In my Android mobile, I clicked from the phone and saw settings-> Wireless Controls->Wifi Settings and tapped on the network I have connected to. It popped up a Dialog with network status, level, speed, signal strength, IP address and security type. So just I got an IP address of network.
How can I get IP addresses of other wifi enabled devices by giving (known IP address got from my mobile) as a Input?
Actually to be clear, how to give specific known IP address as a Input and must be able to get other Unknown Ip addresses of Wifi enabled devices connected on the same network programmatically in Android 2.3 ?
For getting the IP Address you can check getIpAddress() in WifiInfo
Pseudo Code,
WifiManager mWifiManager = (WifiManager)
getSystemService(Context.WIFI_SERVICE);
WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();
Log.e("IP in Mask Integer", mWifiInfo.getIpAddress()+"");
Log.e("IP Address", intToIP(mWifiInfo.getIpAddress())+"");
public String intToIP(int i) {
return (( i & 0xFF)+ "."+((i >> 8 ) & 0xFF)+
"."+((i >> 16 ) & 0xFF)+"."+((i >> 24 ) & 0xFF));
}
To find other devices in the same network you need to SCAN that network.
Scanning means to find the possible IPs in your subnet (using your IP address and subnet mask you can find the possible range and usually for home routers it is between x.x.x.1 ~ x.x.x.254) then iterate through these IPs and for each IP do PING or try to connect with TCP/UDP to some/all ports until you get a response which means there is an active device using that IP. However, it you get no response at all then it might be that there is no device using that IP or the device is filtering these requests (a firewall dropping your packages) or simply that device doesn't have any listening services.
To learn more about this check out some well known tools like nmap
WifiManager myWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo myWifiInfo = myWifiManager.getConnectionInfo();
int myIp = myWifiInfo.getIpAddress();
textWifiManager.setText(myWifiManager.toString());
textWifiInfo.setText(myWifiInfo.toString());
int intMyIp3 = myIp/0x1000000;
int intMyIp3mod = myIp%0x1000000;
int intMyIp2 = intMyIp3mod/0x10000;
int intMyIp2mod = intMyIp3mod%0x10000;
int intMyIp1 = intMyIp2mod/0x100;
int intMyIp0 = intMyIp2mod%0x100;
textVIewIp.setText(String.valueOf(intMyIp0)
+ "." + String.valueOf(intMyIp1)
+ "." + String.valueOf(intMyIp2)
+ "." + String.valueOf(intMyIp3)
);
Also have to modify AndroidManifest.xml to grant permission of android.permission.ACCESS_WIFI_STATE.
click settings, > wireless & networks > then wlan > click the options button on your phone (it should be beside your home button thingy) then click advanced :)
I'm trying to listen on a port using ServerSocket on an Android device. I want to be able to connect to this port over WiFi using a computer on the same network.
I get no exception when binding it to a port, however when I check netstat it says:
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 (null):4040 (null):* LISTEN
I've tried countless ways of binding it to localhost, 0.0.0.0, the WiFi LAN IP address of the device with SocketInetAddress and InetAddress.getByName. Nothing seems to work.
When I try to connect to the port from a computer in the same WiFi (I've tried both netcat and Java's Socket.connect()), all I can see in Wireshark is an ARP request:
Who has [phone's LAN address]? Tell [computer LAN address].
This request repeat itself until timed out.
I've tried the reverse way, by setting the ServerSocket on the computer and connecting to that port from the phone, that works very well.
My testing phone is an Samsung Spica i5700 with a custom ROM.
Any ideas?
Edit:
The code is simple as this:
ServerSocket server = new ServerSocket();
server.setReuseAddr(true);
server.setTimeout(0);
server.bind(new InetSocketAddress(4040));
Socket client = null;
while((client = server.accept()) == null);
// Connected
enter code here
enter code here
Instead of using server.bind, try initializing the server socket like this:
server = new ServerSocket(4040);
Also, server.accept() will actually block until a connection is made, so you don't need that while loop (see: http://download.oracle.com/javase/1.5.0/docs/api/java/net/ServerSocket.html#accept() )
I struggled with this too and was only able to connect to my Android server by using:
ServerSocket myServerSocket = new ServerSocket();
String hostname = getLocalIpAddress();
myServerSocket.bind(new InetSocketAddress(hostname, myPort));
Where hostname was the local IP, which I got using the getLocalIpAddress() function from this page:
https://github.com/Teaonly/android-eye/blob/master/src/teaonly/droideye/MainActivity.java
I was able to get this working by using
ServerSocket server = new ServerSocket( myTcpPort, 0, addr );
where addr = InetAddress of your phone. Otherwise, it only seems to bind to localhost (127.0.0.1). Also, I'm using port 8080.
How can I find the IP address of the an HTC incredible connected to Verizon's network?
My other question - do I have to make any changes to my App to run it on a cellular network? Till now the App was running on a Nexus One connected to a local Wi-Fi network.
Thanks.
Through mobile network, to check your IP run the command below:
ifconfig rmnet0
or application like 'Android Status' can be handy. Get it from the market.
To get IP address info look at this example. Might need a tweak for your CDMA.
You need not modify anything to get it working on Mobile n/w
You can use NetworkInterface.getNetworkInterfaces();, then addresses = intf.getInetAddresses(); to enumerate all the IP addresses on all the interfaces. You're looking for an address associated with a PDP.
That should work. I'm currently looking for a neater way.
To get the internal IP Address you can use the following snippet of code:
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
byte[] address = inetAddress.getAddress();
}
}
Note: This will return the private network IP Address.
If you want the public IP Address you will need to use STUN (try jSTUN).
Hope that helps!