How do you check if you can connect to the internet via java? One way would be:
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
... if we got here, we should have net ...
But is there something more appropriate to perform that task, especially if you need to do consecutive checks very often and a loss of internet connection is highly probable?
You should connect to the place that your actual application needs. Otherwise you're testing whether you have a connection to somewhere irrelevant (Google in this case).
In particular, if you're trying to talk to a web service, and if you're in control of the web service, it would be a good idea to have some sort of cheap "get the status" web method. That way you have a much better idea of whether your "real" call is likely to work.
In other cases, just opening a connection to a port that should be open may be enough - or sending a ping. InetAddress.isReachable may well be an appropriate API for your needs here.
The code you basically provided, plus a call to connect should be sufficient. So yeah, it could be that just Google's not available but some other site you need to contact is on but how likely is that? Also, this code should only execute when you actually fail to access your external resource (in a catch block to try and figure out what the cause of the failure was) so I'd say that if both your external resource of interest and Google are not available chances are you have a net connectivity problem.
private static boolean netIsAvailable() {
try {
final URL url = new URL("http://www.google.com");
final URLConnection conn = url.openConnection();
conn.connect();
conn.getInputStream().close();
return true;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
return false;
}
}
People have suggested using INetAddress.isReachable. The problem is that some sites configure their firewalls to block ICMP Ping messages. So a "ping" might fail even though the web service is accessible.
And of course, the reverse is true as well. A host may respond to a ping even though the webserver is down.
And of course, a machine may be unable to connect directly to certain (or all) web servers due to local firewall restrictions.
The fundamental problem is that "can connect to the internet" is an ill-defined question, and this kind of thing is difficult to test without:
information on the user's machine and "local" networking environment, and
information on what the app needs to access.
So generally, the simplest solution is for an app to just try to access whatever it needs to access, and fall back on human intelligence to do the diagnosis.
If you're on java 6 can use NetworkInterface to check for available network interfaces.
I.e. something like this:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback())
return true;
}
Haven't tried it myself, yet.
This code should do the job reliably.
Note that when using the try-with-resources statement we don't need to close the resources.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class InternetAvailabilityChecker
{
public static boolean isInternetAvailable() throws IOException
{
return isHostAvailable("google.com") || isHostAvailable("amazon.com")
|| isHostAvailable("facebook.com")|| isHostAvailable("apple.com");
}
private static boolean isHostAvailable(String hostName) throws IOException
{
try(Socket socket = new Socket())
{
int port = 80;
InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
socket.connect(socketAddress, 3000);
return true;
}
catch(UnknownHostException unknownHost)
{
return false;
}
}
}
This code:
"127.0.0.1".equals(InetAddress.getLocalHost().getHostAddress().toString());
Returns - to me - true if offline, and false, otherwise. (well, I don't know if this true to all computers).
This works much faster than the other approaches, up here.
EDIT: I found this only working, if the "flip switch" (on a laptop), or some other system-defined option, for the internet connection, is off. That's, the system itself knows not to look for any IP addresses.
InetAddress.isReachable sometime return false if internet connection exist.
An alternative method to check internet availability in java is : This function make a real ICMP ECHO ping.
public static boolean isReachableByPing(String host) {
try{
String cmd = "";
if(System.getProperty("os.name").startsWith("Windows")) {
// For Windows
cmd = "ping -n 1 " + host;
} else {
// For Linux and OSX
cmd = "ping -c 1 " + host;
}
Process myProcess = Runtime.getRuntime().exec(cmd);
myProcess.waitFor();
if(myProcess.exitValue() == 0) {
return true;
} else {
return false;
}
} catch( Exception e ) {
e.printStackTrace();
return false;
}
}
I usually break it down into three steps.
I first see if I can resolve the domain name to an IP address.
I then try to connect via TCP (port 80 and/or 443) and close gracefully.
Finally, I'll issue an HTTP request and check for a 200 response back.
If it fails at any point, I provide the appropriate error message to the user.
URL url=new URL("http://[any domain]");
URLConnection con=url.openConnection();
/*now errors WILL arise here, i hav tried myself and it always shows "connected" so we'll open an InputStream on the connection, this way we know for sure that we're connected to d internet */
/* Get input stream */
con.getInputStream();
Put the above statements in try catch blocks and if an exception in caught means that there's no internet connection established. :-)
The code using NetworkInterface to wait for the network worked for me until I switched from fixed network address to DHCP. A slight enhancement makes it work also with DHCP:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface interf = interfaces.nextElement();
if (interf.isUp() && !interf.isLoopback()) {
List<InterfaceAddress> adrs = interf.getInterfaceAddresses();
for (Iterator<InterfaceAddress> iter = adrs.iterator(); iter.hasNext();) {
InterfaceAddress adr = iter.next();
InetAddress inadr = adr.getAddress();
if (inadr instanceof Inet4Address) return true;
}
}
}
This works for Java 7 in openSuse 13.1 for IPv4 network. The problem with the original code is that although the interface was up after resuming from suspend, an IPv4 network address was not yet assigned. After waiting for this assignment, the program can connect to servers. But I have no idea what to do in case of IPv6.
1) Figure out where your application needs to be connecting to.
2) Set up a worker process to check InetAddress.isReachable to monitor the connection to that address.
This code is contained within a jUnit test class I use to test if a connection is available. I always receive a connection, but if you check the content length it should be -1 if not known :
try {
URL url = new URL("http://www.google.com");
URLConnection connection = url.openConnection();
if(connection.getContentLength() == -1){
fail("Failed to verify connection");
}
}
catch (IOException e) {
fail("Failed to open a connection");
e.printStackTrace();
}
public boolean checkInternetConnection()
{
boolean status = false;
Socket sock = new Socket();
InetSocketAddress address = new InetSocketAddress("www.google.com", 80);
try
{
sock.connect(address, 3000);
if(sock.isConnected()) status = true;
}
catch(Exception e)
{
status = false;
}
finally
{
try
{
sock.close();
}
catch(Exception e){}
}
return status;
}
You can simply write like this
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main {
private static final String HOST = "localhost";
public static void main(String[] args) throws UnknownHostException {
boolean isConnected = !HOST.equals(InetAddress.getLocalHost().getHostAddress().toString());
if (isConnected) System.out.println("Connected");
else System.out.println("Not connected");
}
}
There are (nowadays) APIs for this, but they are platform specific:
On Android ConnectivityManager (https://developer.android.com/training/basics/network-ops/reading-network-state) does everything you need.
On Windows INetworkListManager::GetConnectivity (for which you'll need a JNI)
On generic Linux, you are probably stuck with testing if you have access to a DNS server and Google, as above.
there is probably an Apple way to do this as well
(I'd use the specific tools where available)
This have worked well for me.
try{
InetAddress addr = InetAddress.getByName("google.com" );
}catch(IOException e){
JOptionPane.showMessageDialog(new JFrame(),"No Internet connection.\nTry again later", "Network Error", JOptionPane.ERROR_MESSAGE);
}
There is also a gradle option --offline which maybe results in the behavior you want.
The following piece of code allows us to get the status of the network on our Android device
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView mtv=findViewById(R.id.textv);
ConnectivityManager connectivityManager=
(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(((Network)connectivityManager.getActiveNetwork())!=null)
mtv.setText("true");
else
mtv.setText("fasle");
}
}
}
Related
public void connect() {
final String msg = "";
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
s = new Socket("192.168.1.3", 1337);
textView.setText("Connection acquired");
out = s.getOutputStream();
output = new PrintWriter(out);
output.println(msg);
textView.setText("message sent : " + msg.length());
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
I am using the above code to connect to desired IP [192.168.1.3]... I have created another program at the other end... The problem is that the IP sometimes changes to 192.168.1.4 or 192.168.1.6... and when I use another network it changes to 192.168.43.2... now due to this I have to go every time into the code and change it manually....
Is there any function or any other thing that might search for IPs available then check if desired port exists and then connect... Thanks in advance
That's why DNS names exist. If you use an IP address, you have to use that exact address. If you use DNS, you do a name->IP lookup. Get a dynamic DNS provider and use that to give your server a name.
You really do not want to start port scanning to find open ports. You will be treated as an attacker and kicked off the network, because you really would be doing something attackers do.
I want to check whether the current LDAP server is up or down before doing an authentication. I am using UnboundID LDAP SDK. IS there any possible way to do this?
Check if the port is up and running. It's pur Java. No SSL Factory or SSL Context or Credentials needed. Has a time out in milliseconds, if the package is dropped by a firewall.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
public static boolean isPortReachable(String host, int port, int timeOutMS) {
try (Socket serverSocket = new Socket();) {
serverSocket.connect(new InetSocketAddress(host, port), timeOutMS);
return true;
} catch (final IOException e) { /* Ignore, Port not reachable */ }
return false;
}
Usage for LDAP or LDAPS:
if (isPortReachable(hostname, 389, 200)) { ... }
if (isPortReachable(hostname, 636, 200)) { ... }
There is a method isConnected():
public boolean isConnected()
Indicates whether this connection is currently established.
Returns:
true if this connection is currently established, or false if it is not.
So a simple example something like:
LDAPConnection ldc = new LDAPConnection()
ldc.connect(...);
if (ldc.isConnected())
{
do good stuff
}
else
{
getLDAPConnection(...);
}
Should do the trick.
The best way to test whether any resource is available is simply to try to use it in the normal course of your application, and cope with the errors as they arise.
Otherwise you're trying to predict the future.
We can do this with SSUtil. Here an authenticated entry will not be needed and we can check whether the server is up or down before doing any authentication.
SSLUtil su = new SSLUtil(new TrustAllTrustManager());
SSLSocketFactory sf = su.createSSLSocketFactory();
LDAPConnection connection = new LDAPConnection(sf,"localhost", 10636);
Looking for pros and cons for this solution.
In an Android app, I'm trying to test that the user has a working Internet connection. If you are interested, there is some background in a previous question Detecting limited network connectivity in Android?
The code is basically like:
try {
HttpParams myParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(myParams, 10000);
HttpConnectionParams.setSoTimeout(myParams, 10000);
httpClient = new DefaultHttpClient(myParams);
request = new HttpHead(url);
response = httpClient.execute(request);
statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200)
{
return false;
}
return true;
} catch(Exception e) {
return false;
}
I can control the timeouts for Connection and Socket using HttpConnectionParams. But, if my device is connected to Wifi, but the wifi has no Internet access, the error I'm getting in the exception is:
libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address
associated with hostname)
Unable to resolve host "www.example.com": No address associated with
hostname
Which looks like it timed out on a DNS lookup. Can I control the timeout of the DNS Lookup? httpClient.execute is taking about 45 seconds to fail with the exception noted above. I'd like it to give up sooner.
I did a little homework and it seems that you cannot adjust the DNS lookup timeout. So, I figured a better approach would be to an explicit DNS lookup so I could control it (and hopefully have the result cached to speed the next attempt). So that led me to the simple:
InetAddress addr = InetAddress.getByName(hostname);
but this also had a 45 second timeout. Others had mentioned that there was no control of the timeout for getByName(). Finally, I stumbled on a simple solution, just launch the lookup in a separate thread and manage your own timeout. This blog post shows this quite well.
private static boolean testDNS(String hostname) {
try
{
DNSResolver dnsRes = new DNSResolver(hostname);
Thread t = new Thread(dnsRes);
t.start();
t.join(1000);
InetAddress inetAddr = dnsRes.get();
return inetAddr != null;
}
catch(Exception e)
{
return false;
}
}
private static class DNSResolver implements Runnable {
private String domain;
private InetAddress inetAddr;
public DNSResolver(String domain) {
this.domain = domain;
}
public void run() {
try {
InetAddress addr = InetAddress.getByName(domain);
set(addr);
} catch (UnknownHostException e) {
}
}
public synchronized void set(InetAddress inetAddr) {
this.inetAddr = inetAddr;
}
public synchronized InetAddress get() {
return inetAddr;
}
}
Using this I can first test if the device can resolve the host name, then if it successful to the full connectivity test.
In my android application I need to connect to the internet to check for the time. This snippet works very nicely in mobile networks and in WiFi-Networks with no proxy enabled:
public class MyTimeGetterTask {
#Override
protected Long doInBackground(Void... params) {
WebTimeSntpClient client = new WebTimeSntpClient();
if (client.requestTime("time-d.nist.gov", 3000)) {
long now = client.getNtpTime() + SystemClock.elapsedRealtime()
- client.getNtpTimeReference();
return now;
}
else {
return null;
}
}
}
The core elements of the WebTimeSntpClient are as follows:
public class WebTimeSntpClient {
public boolean requestTime(String host, int timeout) {
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
socket.setSoTimeout(timeout);
InetAddress address = InetAddress.getByName(host);
byte[] buffer = new byte[NTP_PACKET_SIZE];
DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
...
socket.send(request);
DatagramPacket response = new DatagramPacket(buffer, buffer.length);
socket.receive(response);
...
} catch (IOException ex) {
return false;
} finally {
if (socket != null) {
socket.close();
}
}
return true;
}
}
However when I'm in the office and the WiFi requires me to configure a proxy (which I did in the settings by long-pressing on the network and then clicking "modify network" - as of Android API level 17) the connection fails.
Now I have looked up quite a lot of very good posts about proxies on the internet and especially here on SO, but absolutely none of them seem to answer this (to me) very simple question:
How do I force my application to use the proxy that is already configured in the settings?
Instead, they focus on more advanced issues like:
How to GET a proxy from the system
How to SET ip information to the system yourself
and much much more about how to make existing applications from the play store use a proxy
Again: I want to stress that this is not my intention, I simply want my app to connect to the internet, no matter what. Is there some System.useWifiProxyIfAvailable(true) method? I'm sure I must have missed a post somewhere here...
You are trying to use SNTP trough a proxy that only allows HTTP/HTTPS.
Your alternative is to use some HTTP service providing the current time, which will be more than enough for most user level applications.
Give http://www.timeapi.org/utc/now a try, however if you are publishing an application using this service you should check the terms and conditions.
I am coding a basic app, a chat that sends message through the network using multicast and unicast, depending on the situation. So far, no problem, until a while ago when I began the MulticastSocket part. I have a BindException when I run this basic code (I removed all my other methods that do not concern the part with my problem) :
private MulticastSocket socket_multicast;
private int port;
private InetAddress multicast_address;
public void setPort(int p) {
port = p;
}
public void setMulticastAddress(String s) {
try {
multicast_address = InetAddress.getByName(s);
} catch (IOException e) {
e.printStackTrace();
}
}
public void joinGroup() {
System.out.println("Port : "+port+"\n #IP : "+multicast_address+"\n");
try {
socket_multicast = new MulticastSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
try {
socket_multicast.joinGroup(multicast_address);
} catch (IOException e) {
e.printStackTrace();
}
}
When I run this piece of code, I have the following error (I put 225.1.1.1 and 4567 in the GUI):
Port : 4567
#IP : /225.1.1.1
java.net.BindException: Address already in use
at java.net.PlainDatagramSocketImpl.bind0(Native Method)
at
java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:85)
at java.net.DatagramSocket.bind(DatagramSocket.java:373)
at java.net.MulticastSocket.<init>(MulticastSocket.java:165)
at java.net.MulticastSocket.<init>(MulticastSocket.java:130)
at networkinterface.MulticastIF.joinGroup(MulticastIF.java:61)
No matter which combinason of IP and port I put, always get the same error. I even restarted my computer, it made no changes.
Notes : To test, I do a right click in my class with the main in the Package view, then "Run as -> Java application". Does Eclipse makes some kind of virtual machine when I do that, or only uses the loopback address 127.0.0.1, or whatever ? When I print the result of InetAddress.getLocalHost(); I've got "akee-netbook/127.0.1.1". Since I use Unicast and Multicast, Maybe it only uses the loopback address, and tries to bind on an already-binded address. If so, how can I properly test my app ? I don't know if I am being clear, if not, tell me !
One last thing, Why is there a slash when I print my ip address? Will it be a problem later ? or is it smth that comes from the toString() method?
Are you running this on a linux system? If so, have you compiled multicasting into the kernel or loaded the module for it?
Regarding the toString(), see the javadocs for InetAddress.toString()
Huh, I know where I went wrong. I am using an UDP socket (DatagramSocket) with the #IP/port, and then I try to bind again on the same #IP/port with a MulticastSocket. Because Multicast uses UDP I presumed that I could use the same socket for both Unicast and Multicast traffic, it seems that it doesn't work that way.
Anyway, thank's for your answers and sorry for taking your time over a n00b problem, solved with two characters :
socket_multicast = new MulticastSocket(port);
replaced with
socket_multicast = new MulticastSocket(port+1);
-_-"