Java application getting different IP from android application - Why? - java

I made one android application that needs to connect one local database provided by wamp server. First using the android virtual device (AVD) my IP to connect the server first time used to be: 10.0.2.2. My AVD was connecting fine, but when I tried to connect direct on my device he wasn't finding the local server with this 10.0.2.2 IP. At this point I've changed IP to 192.168.1.5 which was my LAN cable IP, both device and AVD were running without problems... but sometimes I need to change my connection to wifi, which changes the IP..also, I realized that fix one IP in my source code will be a problem to release the android app, since other people will have other LAN IP address.
To solve this problem, I've started to look for a solution, such as acquire the LAN IP dynamically. For this purpose I built this Java application as test:
public class test {
public static void main(String[] args) throws Exception
{
String roundHost = null;
Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
for (; n.hasMoreElements();)
{
NetworkInterface e = n.nextElement();
Enumeration<InetAddress> a = e.getInetAddresses();
for (; a.hasMoreElements();)
{
InetAddress addr = a.nextElement();
if (addr.isSiteLocalAddress()){
String pureHost = addr.getByName(addr.getHostName()).toString();
roundHost = addr.getHostAddress();
pureHost = pureHost.substring(addr.getHostName().length()+1);
if(!roundHost.equals(pureHost))
break;
}
}
}
System.out.println(roundHost);
}
}
As output, this java application gives me my correct LAN wifi IP or even my LAN cable IP which is 192.168.1.3 or 192.168.1.7. From here I made one "IPParser" to use on my android app:
public class IPParser {
String pureHost, roundHost = null;
public IPParser() throws UnknownHostException{
Enumeration<NetworkInterface> n = null;
try {
n = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e1) {
e1.printStackTrace();
}
for (; n.hasMoreElements();)
{
NetworkInterface e = n.nextElement();
Enumeration<InetAddress> a = e.getInetAddresses();
for (; a.hasMoreElements();)
{
InetAddress addr = a.nextElement();
if (addr.isSiteLocalAddress()){
pureHost = addr.getByName(addr.getHostName()).toString();
roundHost = addr.getHostAddress();
pureHost = pureHost.substring(addr.getHostName().length()+1);
if(!roundHost.equals(pureHost))
break;
}
}
}
}
public String returnIp() {
return roundHost;
}
}
As you can see it's pretty similar; the difference is just some structural changes to adapt the needed syntax. And now comes the real problem: When I try to run this parser inside my AVD, my ip is 10.0.2.15 and running directly in my device the ip return is 192.168.1.6 - Obviously the android app is crashing because it can't find the local server to connect.
My IP config information:
I'm not an expert in network, so I ask, take it easy and if I said something technically wrong or adjacents please edit and correct me..finally I ask:
Why this is happening and what's possible to do to solve this problem?

The IPs you mention (10.0.2.2 and 192.168.1.5) are from two different networks, which makes sense since the documentation states that:
Each instance of the emulator runs behind a virtual router/firewall
service that isolates it from your development machine's network
interfaces and settings and from the internet. An emulated device can
not see your development machine or other emulator instances on the
network. Instead, it sees only that it is connected through Ethernet
to a router/firewall.
The virtual router for each instance manages the 10.0.2/24 network
address space — all addresses managed by the router are in the form of
10.0.2., where is a number. Addresses within this space are pre-allocated by the emulator/router as follows:
What this means is that when using the AVD there is a virtual network that is created which the device and the computer are part of. In your case your local machine takes the address 10.0.2.2 in this virtual network and the AVD 10.0.2.15. But when you connect directly through your device, the computer's IP (as well as the device's) is in the LAN's address space (i.e. 192.168.1.5 and 192.168.1.6).
The code you posted resolves the IP address of the host, but if you want the device to resolve automatically the server's IP address and you can guarantee they will always be both connected to the same LAN, then you can use multicast UDP messages (I didn't find a really good source but you can start here, here and here). This type of communication sends a UDP datagram to the network to a specific multicast IP address and port, to which other devices in the network are listening. I've used this scheme in an Android application that needed to find a computer in the network so I know for a fact that it works. I can share some code if you need to.
EDIT
The following snippets of code are the ones that implement the search of computers in the network. The Android application this was used in could control the mouse and keyboard of any computer in the network that had the server application running.
Android Client
public void findComputers(View v) {
try {
int port = 4444;
String multicastAddr = "224.168.1.0";
DatagramSocket socket = new DatagramSocket(port);
socket.setSoTimeout(300);
InetAddress group = InetAddress
.getByName(multicastAddr);
DatagramPacket packet = new DatagramPacket(new byte[] { 1 }, 1,
group, port);
socket.send(packet);
// Give time to the servers to respond
Thread.sleep(100);
while (true) {
try {
// Listen for the servers responses
byte[] buffer = new byte[256];
packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String data = new String(packet.getData());
// Information sent from servers include the host's name
// and IP addres separated by a semicolon.
String[] parts = data.split(";");
// Add a server to the result list.
Computer computer = new Computer(parts[1].trim(),
parts[0].trim());
this.computers.put(computer.getName(), computer);
} catch (InterruptedIOException ex) {
break;
}
}
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
String output = "No computers found.";
if (this.computers.size() > 0) {
output = this.computers.size() + " computer(s) found.";
this.fillComputers();
}
Toast.makeText(this, output, Toast.LENGTH_SHORT).show();
}
Server
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* Receives UDP broadcast packets in the default port requesting for server name
* and IP, broadcasting the information in return.
*
* #author jfacorro
*
*/
public class NameResolverService extends Thread {
private InetAddress localAddress = null;
private byte[] localAddressData = null;
private MulticastSocket socket = null;
private boolean exit = false;
public NameResolverService() {
}
public void exit() {
this.exit = true;
this.socket.close();
}
#Override
public void run() {
try {
int port = 4444;
String multicastAddr = "224.168.1.0";
// Get current address
this.localAddress = InetAddress.getLocalHost();
this.socket = new MulticastSocket(port);
InetAddress group = InetAddress.getByName(multicastAddr);
this.socket.joinGroup(group);
this.localAddressData = (this.localAddress.getHostAddress() + ";" + this.localAddress
.getHostName()).getBytes();
} catch (IOException ex) {
this.notified.notified(ex.getMessage());
ex.printStackTrace();
}
while (!this.exit) {
try {
byte[] buffer = new byte[1];
DatagramPacket packet = new DatagramPacket(buffer,
buffer.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(this.localAddressData,
this.localAddressData.length, address, port);
socket.send(packet);
} catch (IOException e) {
if(!this.exit)
e.printStackTrace();
}
}
this.socket.close();
}
}

Related

AudioStream IP Address

I'm trying to make a wireless audio connection between two android devices. So I found AudioStream class, and I have the partial code like this:
public String getMobileIP() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = (NetworkInterface) en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf
.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
String ipaddress = inetAddress .getHostAddress().toString();
return ipaddress;
}
}
}
} catch (SocketException ex) {
Log.e("tag", "Exception in Get IP Address: " + ex.toString());
}
return null;
}
public void Connect()
{
String ipaa=getMobileIP();
InetAddress local = InetAddress.getByName(ipaa);
AudioStream audioStream = new AudioStream(local); <<----- exception
...
...
}
I want both phones to connect by voice using the AudioStream so that both people can talk and hear each other like a walkie-talkie.
I decide to use the mobile network IP address of the phone (Not the WiFi address), but when I do that the above code crashes when I use that to create the AudioStream.
I want the users to be able to talk to each other weather they are on WiFi or not (using mobile network).
Does anybody know how to fix this?
Documentation says exception occurs if the address cannot be bound or a problem occurs during binding. I think you could accomplish through Wi-fi because you were in the same network. However, when using mobile data IPs of ISPs (Internet Service Providers) might not see each other (it depends on ISP). Hence connection cannot be established.
Obvious solution is that your voice should go through some server where both clients can see it.

Cannot capture UDP broadcast packets with Java DatagramSocket

I am creating a client-server communication application and would like the client to be able to detect and connect to the server automatically, given that they are on the same network.
Previously, my code was working across a Linux and Windows machine. I would broadcast a simple message and it could be read. I could also see the message while watching network traffic with Wireshark.
The approach I am taking is to
Get the broadcast address(es) on the network on the server.
For a given duration, broadcast a message (soon to be the server IP)
On the client side, wait until a message is received.
I am quite new to networking, so any obvious errors may not be immediately obvious to me.
Server broadcast code:
public class Broadcaster {
/* ... */
public void pulse() throws InterruptedException, IOException, SocketException {
Long elapsed = new Date().getTime();
Long timeout = elapsed + this.duration;
DatagramPacket packet = new DatagramPacket(this.message.getBytes(), this.message.length());
HashSet<InetAddress> channels = Broadcaster.getBroadcastChannels();
while(elapsed <= timeout) {
for(InetAddress channel : channels) {
DatagramSocket socket = new DatagramSocket(this.port);
socket.setBroadcast(true);
socket.connect(channel, this.port);
socket.send(packet);
System.out.println("Broadcast sent to " + channel.getHostAddress() + " (" + socket.getPort() + "): " + this.message);
socket.close();
}
Thread.sleep(this.frequency);
elapsed = new Date().getTime();
}
}
private static HashSet<InetAddress> getBroadcastChannels() throws SocketException {
/* Returns 192.168.0.255 */
}
public static void main(String[] args) {
Broadcaster heart = new Broadcaster("Hello from the Raspberry Pi!", 120000, 5000, 8027);
try {
heart.pulse();
} catch(SocketException e) {
/* ...etc... */
} finally {
System.out.println("Broadcasting completed.");
}
}
}
Client code:
public class BroadcastListener {
private int port;
private int length;
public BroadcastListener(int length, int port) {
this.port = port;
this.length = length;
}
public String getNext() throws IOException {
byte buffer[] = new byte[this.length];
DatagramSocket socket = new DatagramSocket(this.port);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Waiting on " + socket.getLocalSocketAddress());
socket.receive(packet);
socket.close();
return new String(buffer);
}
public static void main(String[] args) {
System.out.println("Listening for network broadcasts...");
BroadcastListener broadcast = new BroadcastListener(128, 8027);
try {
System.out.println("Received broadcast: " + broadcast.getNext());
} catch(IOException e) {
System.out.println("Could not receive broadcasts:");
System.out.println(e.getMessage());
}
}
}
The broadcast/netmask address as seen on both devices ifconfig output is netmask 255.255.255.0 broadcast 192.168.0.255
What confuses me the most is that Wireshark is still seeing the broadcast but when I run the client Java program, it just sits at socket.receive(packet);
Wireshark screenshot on Imgur
Both client & server are on port 8027. It is clear that the broadcaster is working, but the client broadcast listener is not. Does anyone have any idea what could be happening? Thanks!
As mentioned in the comments: Check your firewall :-)
Another thing i recognized was that if I sniff with wireshark, no other processes could receive that datagrams. After realizing that, I wrote a nodejs script, which exclusive=false by default but even that did not help. Maybe there is a kernel flag or something, that UDP datagrams cannot be 'consumed' by one process.
It looks like your server may be brodcasting on a different address than your client. Your client is not being assigned an InetAddress, try using this constructor for your socket in BroadcastListener
DatagramSocket socket = new DatagramSocket(new InetSocketAddress("192.168.0.255", this.port));
If that doesnt work you might try binding both your server and client to 127.0.0.1
You keep creating and destroying DatagramSockets. If the packet arrives at your host at a moment when you don't have a DatagramSocket bound to the port, it will be thrown away.
Create one DatagramSocket and leave it open for this life of this code.

Client-Server Program, can connect from Java client but not from Android

I have a working Java client/server program which is very straightforward and basic. This works fine. However, I am now trying to write an Android client, and I have been unable to connect to the server from my android client. I am using almost identical code for the android networking code as I use for the normal client. My android code is simple, all it does is starts this thread from onCreate:
private int serverPort = 8889;
private String serverIP = "192.168.5.230";
private Socket socket = null;
private Thread clientThread = new Thread("ClientThread") {
#Override
public void run() {
try {
socket = new Socket();
socket.connect(new InetSocketAddress(serverIP, serverPort), 1000);
DataInputStream din = new DataInputStream( socket.getInputStream());
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
while (true) {
String message = din.readUTF();
setPicture("picture1");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
The port is the correct port my server is running on, as is the ip address (which I got from ifconfig since I know you cannot use localhost). When I run my normal pc client with the same port and IP address, the connection goes through. But when I run this code on my android device, the socket timesout when I try to connect.
Does anyone have any suggestions for where I am going wrong?
Double check that you added the permission requirement in the manifest file:
<uses-permission android:name="android.permission.INTERNET" />
But, possibly more importantly, 192.168.x.x is a local or non-routable network so you need to be on the same network, or one that knows how to reach the 192.168.5.230 address. You say that it doesn't work when you try it on your device -- are you running on local wifi when you run or are you on your mobile network? If you're on mobile, try it from wifi.

Server not receiving message from client with correct IP and port opened

What can cause this to happen?
I moved my laptop to a friends house to work on this project. I opened the same port on his xfinity router, and changed all areas of my code to his IP. However it appears that the client is sending a message and the server has never getting past this part of code
System.out.println("running server!");
int nreq = 1;
try{
//SET ME PORT
ServerSocket sock = new ServerSocket(7332);
for(;;){
Socket newsock = sock.accept();
System.out.println("Creating thread...");
//Broken Old Login crap, needs reworked for map n stuff anyhow now
// Thread t = new ThreadHandler(newsock, nreq);
Thread t = new RequestInterpreter(newsock, nreq);
//t.run();
t.start();
nreq++;
}
}
catch(Exception e)
{
e.printStackTrace();
}
It never gets to print "Creating thread". I'm not sure where to begin with what could be going wrong here?
The only thing that has changed is the house, IP, router, and internet. Works everywhere else. What about those changing could block the client from sending a
Here is a test client I wrote also.
import java.io.DataInputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class testClientConnection {
public static void main(String[] args) {
System.out.println("Starting testConnection");
try{
Socket s = new Socket("xx.xx.xx.xxx", 7332);
DataInputStream fromServer = new DataInputStream(s.getInputStream());
PrintWriter toServer = new PrintWriter(s.getOutputStream(), true);
toServer.println("account name");
toServer.println("password");
toServer.println("Login");
System.out.println("Sent message...");
String response = fromServer.readLine().toString();
//Toast the result here? //testing
System.out.println("response: " + response);
if (response.equals("Login Success")) {
System.out.println("Login Success!!!");
}
}
catch(Exception e){ /
}
}
}
HUGE UPDATE!
Ok so my client was an android phone and I turned the wifi off, so it fell onto 4g-LTE. Then it worked. So... Something is blocking the client side code. What might that be?
The firewall on your friend's router is the usual suspect.
Second suspect is the firewall on the target machine.
Try disabling those.
The problem will be NAT on the router.
Servers don't work behind NAT devices unless you set up port-forwarding so that the router knows where to send an incoming request from outside.

Java Networking "Connection Refused: Connect"

I have been trying to get a simple networking test program to run with no results.
Server:
import java.io.*;
import java.net.*;
public class ServerTest {
public static void main(String[] args) {
final int PORT_NUMBER = 44827;
while(true) {
try {
//Listen on port
ServerSocket serverSock = new ServerSocket(PORT_NUMBER);
System.out.println("Listening...");
//Get connection
Socket clientSock = serverSock.accept();
System.out.println("Connected client");
//Get input
BufferedReader br = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
System.out.println(br.readLine());
br.close();
serverSock.close();
clientSock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
Client:
import java.io.*;
import java.net.*;
public class ClientTest {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44827;
final String HOSTNAME = "xx.xx.xx.xx";
//Attempt to connect
try {
Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
//Output
out.println("Test");
out.flush();
out.close();
sock.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
The program works just fine when I use 127.0.0.1 or my internal IP for the hostname. But whenever I switch to my external IP address, it throws a java.net.ConnectException: Connection refused: connect error.
I purposely picked such an uncommon port to see if that was the problem, with no luck.
I can connect with no problems using telnet, but when I try to access the port with canyouseeme.org, it tells me the connection timed out.
I even tried to disable all firewalls and antivirus including the Windows default ones and the router firewall, with all ports forwarded and DMZ enabled, and it still says that the connection timed out. I use Comcast as my ISP, and I doubt that they block such a random port.
When I use a packet tracer, it shows TCP traffic with my computer sending SYN and receiving RST/ACK, so it looks like a standard blocked port, and no other suspicious packet traffic was going on.
I have no idea what is going on at this point; I have pretty much tried every trick I know. If anyone know why the port might be blocked, or at least some way to make the program work, it would be very helpful.
These problem comes under the following situations:
Client and Server, either or both of them are not in network.
Server is not running.
Server is running but not listening on port, client is trying to connect.
Firewall is not permitted for host-port combination.
Host Port combination is incorrect.
Incorrect protocol in Connecting String.
How to solve the problem:
First you ping destination server. If that is pinging properly,
then the client and server are both in network.
Try connected to server host and port using telnet. If you are
able to connect with it, then you're making some mistakes in the client code.
For what it's worth, your code works fine on my system.
I hate to say it, but it sounds like a firewall issue (which I know you've already triple-checked) or a Comcast issue, which is more possible than you might think. I'd test your ISP.
Likely the server socket is only being bound to the localhost address. You can bind it to a specific IP address using the 3-argument form of the constructor.
I assume you are using a Router to connect to Internet. You should do Port Forwarding to let public access your internal network. Have a look at How do you get Java sockets working with public IPs?
I have also written a blog post about Port forwarding, you might wanna have a look :) http://happycoders.wordpress.com/2010/10/03/how-to-setup-a-web-server-by-yourself/
But I still couldn't get this accessed over public IP, working on it now...
I had the same problem because sometimes the client started before server and, when he tried to set up the connection, it couldn't find a running server.
My first (not so elegant) solution was to stop the client for a while using the sleep method:
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
I use this code just before the client connection, in your example, just before Socket sock = new Socket(HOSTNAME, PORT_NUMBER);
My second solution was based on this answer. Basically I created a method in the client class, this method tries to connect to the server and, if the connection fails, it waits two seconds before retry.
This is my method:
private Socket createClientSocket(String clientName, int port){
boolean scanning = true;
Socket socket = null;
int numberOfTry = 0;
while (scanning && numberOfTry < 10){
numberOfTry++;
try {
socket = new Socket(clientName, port);
scanning = false;
} catch (IOException e) {
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
return socket;
}
As you can see this method tries to create a socket for ten times, then returns a null value for socket, so be carefull and check the result.
Your code should become:
Socket sock = createClientSocket(HOSTNAME, PORT_NUMBER);
if(null == sock){ //log error... }
This solution helped me, I hope it helps you as well. ;-)

Categories

Resources