I have seen that this question had been asked before in SO. Some of the threads are:
How to check if internet connection is present in java.
Detect internet Connection using Java.
Why does InetAddress.isReachable return false, when I can ping the IP address?.
All these threads are pretty old. The approaches that are defined there are:
Opening an HttpURLConnection by openConnection().
Checking InetAddress.isReachable.
Executing ping command through Process and processing the output.
I have seen if I use the second approach to check the connectivity with www.google.com then it is returning false, which should not be the result. But the first way works. I cannot use the last way since the respondent himself said it.
I have also seen the following way:
private boolean isConnected(Socket socket, String address) {
if(socket == null) {
throw new NullPointerException("Socket cannot be null");
}
try {
InetSocketAddress inetSocketAddress = new InetSocketAddress(address, 80);
socket.connect(inetSocketAddress);
return true;
} catch (Throwable cause) {
LOGGER.error(cause.getMessage(), cause);
return false;
}
}
By this way I am getting right output. The aforementioned threads mentioned that there is no proper way to validate if the computer is connected to the internet or not. But since these threads are old so I am hoping there might be some new way out there by which I can achieve what I want. Also I have to consider that there are various ways to access internet like LAN, Broadband, Dial Up, DSL etc and some server might block ping access or can block some IP.
Any pointer would be very helpful.
You could use the NetworkInterface class, it has a isUp() method which returns boolean indicating whether the particular interface is up and running (which could indicate if it's used for internet connection).
API: http://docs.oracle.com/javase/7/docs/api/java/net/NetworkInterface.html
Related
I've been working on a peer-to-peer file-sharing project in Java and have come to a wall that I don't begin to know how to break down. I have 2 clients running identical code, both behind NATs (probably, though assumedly not symmetrical NATs), who have accessed their public IP and port via a STUN server. When I attempt to make a connection between them, I get no response and the receiving client does not register an attempt to connect. This issue did not occur with the same code using local IP addresses.
Relevant connection code:
PeerConnection peerConn = new PeerConnection(pd);
PeerMessage toSend = new PeerMessage(msgType, msgData);
peerConn.sendData(toSend);
if (waitReply) {
PeerMessage oneReply = peerConn.receiveData();
while (oneReply != null) {
msgReply.add(oneReply);
oneReply = peerConn.receiveData();
}
}
peerConn.close();
public class PeerConnection {
private final PeerInfo pd;
private SocketInterface s;
public PeerConnection(PeerInfo info) throws IOException {
pd = info;
s = NormalSocketFactory.makeSocket(pd.getHost(), pd.getPort());
}
public void sendData(PeerMessage msg){ s.write(msg.toBytes()); }
public PeerMessage receiveData(){ return new PeerMessage(s); }
public void close() {if (s != null){ s.close(); s = null; } }
Extraneous comments/try-catch and other code bits are omitted for brevity.
I am manually passing in the IP and port given by a STUN server (for testing purposes) into this peer connection, and other code is creating the actual data (connection type, who it's connecting to, etc) but I don't believe the content has any bearing on this as it can handle the input packets being created (as LAN tested has verified).
Am I missing something here? The clients are sitting there listening for a packet but aren't receiving them. Using WireShark (a program I am admittedly brand-new to) shows me that the connections are being reset (specifically that the reset flag is set, something that I in no way do).
.... .... .1.. = Reset: Set
[Expert Info (Warning/Sequence): Connection reset (RST)]
[Connection reset (RST)]
[Severity level: Warning]
[Group: Sequence]
I do not have a signaling server handling this as I do not have plans to host anything for the time being, but I don't much understand how I'd not come across a similar issue with that.
EDIT: After using WaifUPnP to allow ports to open through the firewalls, I still had issues with most connections I tried to test. I don't know if this is a symmetric NAT problem but a few connections have been made. I'm not gonna delete this in case someone else needs it later.
I had this error for quite a while now when i found this.
After using the solution provided by swankjesse the error disappeared.
I just cant seem to understand why this is a solution. I cant find anything online that
explains the reason why this method solves the error.
OkHttp Docs say:
retryOnConnectionFailure
Configure this client to retry or not when a connectivity problem is
encountered. By default, this client silently recovers from the
following problems:
Unreachable IP addresses. If the URL’s host has multiple IP
addresses, failure to reach any individual IP address doesn’t fail the
overall request. This can increase availability of multi-homed
services.
Stale pooled connections. The ConnectionPool reuses sockets to
decrease request latency, but these connections will occasionally time
out.
Unreachable proxy servers. A ProxySelector can be used to attempt multiple proxy servers in sequence, eventually falling back to a
direct connection.
The above is understandable but it does not justify why this is a solution to that error.
Thanks in advance.
This flag allows OkHttpClient to retry a request multiple times when certain conditions are true that mean it is known to be safe. Without this flag the client will return the error immediately for the client to presumably dcide if and when to retry.
private fun isRecoverable(e: IOException, requestSendStarted: Boolean): Boolean {
// If there was a protocol problem, don't recover.
if (e is ProtocolException) {
return false
}
// If there was an interruption don't recover, but if there was a timeout connecting to a route
// we should try the next route (if there is one).
if (e is InterruptedIOException) {
return e is SocketTimeoutException && !requestSendStarted
}
// Look for known client-side or negotiation errors that are unlikely to be fixed by trying
// again with a different route.
if (e is SSLHandshakeException) {
// If the problem was a CertificateException from the X509TrustManager,
// do not retry.
if (e.cause is CertificateException) {
return false
}
}
if (e is SSLPeerUnverifiedException) {
// e.g. a certificate pinning error.
return false
}
// An example of one we might want to retry with a different route is a problem connecting to a
// proxy and would manifest as a standard IOException. Unless it is one we know we should not
// retry, we return true and try a new route.
return true
}
In the most simple case, if we hadn't started sending a request then we know retrying must be safe. Likewise certain response codes like 408 indicate that the server hasn't started any work so we can try again.
I am looking for a bit of efficient code that can assist me in monitoring if a com port is still open using the RX/TX libraries.
Lets say I have a hardware device that communicates to the PC using a virtual com port and that device can be plugged in and out at any time. I want to show a connection status on the pc.
I have tried this with something like a buffered reader below and it registered that the device gets disconnected but I have to re-open the port from scratch in another method.
I am looking from something short like comPort.isOpen () or something?
// Set the value of is running
Start.isRunning = true;
// Check to see if the device is connected
while (Start.isRunning) {
// Try to connect to the device
try {
// Create a Buffered Reader
BufferedReader reader = new BufferedReader(
new InputStreamReader(serialPort.getInputStream()));
// Read the output
if (Character.toString((char) reader.read()).equalsIgnoreCase(
"^")) {
// Set the connected flag
Start.CONNECTED_FLAG = true;
// Set the connected fag
AddComponents.TFconnected.setText("Connected");
}
// Close the reader
reader.close();
// Let the thread sleep
Thread.sleep(500);
}
// Catch a error if the device is disconnected
catch (Exception err) {
// Set the connected flag
Start.CONNECTED_FLAG = false;
// Set the connected fag
AddComponents.TFconnected.setText("Disconnected");
// Let the thread sleep
Thread.sleep(500);
}
}
Disclaimer: Consider this a partial answer because I do not have intimate knowledge of the workings of serial ports, and my tests could not produce anything useful. Posting here regardless in the hopes any of this is helpful.
Unfortunately, as far as I know, there is no way to receive any kind of "connection / disconnection" event messages. Sadly, as I am not intimately familiar with the workings of serial ports, I cannot give you a full and proper explanation. However, from some research, one of the answers posted in that forum had this to say:
There's no event by the system to inform you of [a disconnection event] because that would require exclusive use of the COM port. If you have a SerialPort object created and have opened a port you should get a CDChanged when a devices is plugged in and unplugged from the serial port. That assumes the device follows the pins standards; not all devices do.
Note that the poster, and the link I've provided, are discussing this within the context of C#. However this seems to be related to how the ports work in general, regardless of language, so I am somewhat confident the same can be applied to RXTX Java.
There are some events you can attempt to listen for. In my tests I was only ever able to receive the DATA_AVAILABLE event, however my setup is a bit different (Raspberry PI) and I can't at the moment physically disconnect the device from the port, I can only attempt to block the device file (which may explain the failure of my test).
If you would like to attempt the event listening yourself, have your class implement SerialPortListener, register for the desired events, check the events in your serialEvent method. Here is an example:
public class YourClass implements SerialPortListener{
private SerialPort serialPort;
// ... serial port gets set up at some point ...
public void registerEvents(){
serialPort.addEventListener(this);
// listen to all the events
serialPort.notifyOnBreakInterrupt(true);
serialPort.notifyOnCarrierDetect(true);
serialPort.notifyOnCTS(true);
serialPort.notifyOnDataAvailable(true);
serialPort.notifyOnDSR(true);
serialPort.notifyOnFramingError(true);
serialPort.notifyOnOutputEmpty(true);
serialPort.notifyOnOverrunError(true);
serialPort.notifyOnParityError(true);
serialPort.notifyOnRingIndicator(true);
}
#Override
public void serialEvent(SerialPortEvent event) {
System.out.println("Received event. Type: " + event.getEventType() + ", old value: " + event.getOldValue() + ", new value: " + event.getNewValue());
}
}
If that ultimately fails, I believe the only other alternative is similar to your current solution; attempt to read from the port, and if it fails, consider it disconnected, and set your indicator accordingly. At each iteration, if it is disconnected, attempt to reconnect; if reconnect succeeds, reset your indicator to "connected".
Sorry I cannot be of more assistance. Hopefully some of that may lead to something useful.
Side Note:
If you want to DRY up your code slightly, put the Thread.sleep(500) in a finally block instead, since it appears to be executed regardless.
I have been reading around the topic of getting a list of devices connected to my WIFI hotspot on my phone programmatically.
I found a useful post on stack overflow with the following code and a comment saying
This is incorrect as the ARP tables don't necessarily refresh when a
device disconnects. One say say, that you could simply ping all the
devices in the table to see which IPs are active but it is quite
possible that a device is firewalled to not respond to ICMP request
and your ping would fail. This solution, although a working one, isn't
robust and accurate.
I was wondering, if reading proc/net/arp isn't accurate enough due to refresh issues, how can you force the system to do a refresh to get accurate data?
private int countNumMac()
{
int macCount = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if (splitted != null && splitted.length >= 4) {
// Basic sanity check
String mac = splitted[3];
if (mac.matches("..:..:..:..:..:..")) {
macCount++;
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
br.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (macCount == 0)
return 0;
else
return macCount-1; //One MAC address entry will be for the host.
}
The ARP table is not a distributed list of "hosts that are online." It's a local-only list of "hosts that we've seen on this network."
Once you realize this, you'll note that there's no way of removing entries when someone disconnects other than trying to connect to them. Just have a continuous loop in the background, connecting to each host and sending a single ICMP packet (kinda hard to pull off from Java but Android does come with a ping command-line tool).
Granted, hosts that don't reply to ping will be filtered out but depending on the application that might be acceptable.
Alternatively, just let the user try to connect to any of the listed hosts and gracefully time out when the other party is offline. That's what most networking applications do anyway and is the only foolproof way of checking if the host is online.
Ping may often do its arp request and get arp replies from active hosts even if the icmp echo request is subsequently blocked. Therefore ping can in some cases be used to populate the arp table in order to check it for network presence even if icmp is being actively blocked.
But if this is not accurate enough or feels too crude, network presence can be mapped directly using the arp protocol and without involving protocols higher up in the stack which stand a higher risk of being blocked.
arping is the Linux utility commonly used for manual arp level operations (on Linux).
Here is the source code for arping.
Through quick-googling it appears there are utilities for Android which perform corresponding operations, I also found source code which seems to be for arping on Google Android BusyBox.
The arping utility may be usable as is, assuming of course you ensure its presence on your phone. Alternatively one or both of the code variants may serve as inspiration as to how the problem may be programmatically solved in your own code.
I've got a client-server tiered architecture with the client making RPC-like requests to the server. I'm using Tomcat to host the servlets, and the Apache HttpClient to make requests to it.
My code goes something like this:
private static final HttpConnectionManager CONN_MGR = new MultiThreadedHttpConnectionManager();
final GetMethod get = new GetMethod();
final HttpClient httpClient = new HttpClient(CONN_MGR);
get.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
get.getParams().setParameter(HttpMethodParams.USER_AGENT, USER_AGENT);
get.setQueryString(encodedParams);
int responseCode;
try {
responseCode = httpClient.executeMethod(get);
} catch (final IOException e) {
...
}
if (responseCode != 200)
throw new Exception(...);
String responseHTML;
try {
responseHTML = get.getResponseBodyAsString(100*1024*1024);
} catch (final IOException e) {
...
}
return responseHTML;
It works great in a lightly-loaded environment, but when I'm making hundreds of requests per second I start to see this -
Caused by: java.net.BindException: Address already in use
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:336)
at java.net.Socket.bind(Socket.java:588)
at java.net.Socket.<init>(Socket.java:387)
at java.net.Socket.<init>(Socket.java:263)
at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:80)
at org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory.createSocket(DefaultProtocolSocketFactory.java:122)
at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
Any thoughts on how to fix this? I'm guessing it's something to do with the client trying to reuse the ephemeral client ports, but why is this happening / how can I fix it?
Thanks!
A very good discussion of the problem you are running into can be found here. On the Tomcat side, by default it will use the SO_REUSEADDR option, which will allow the server to reuse sockets which are in TIME_WAIT. Additionally, the Apache http client will by default use keep-alives, and attempt to reuse connections.
Your problems seems to be caused by not calling releaseConnection on the HttpClient. This is required in order for the connection to be reused. Otherwise, the connection will remain open until garbage collector comes and closes it, or the server disconnects the keep-alive. In both cases, it won't be returned to the pool.
With hundreds of connections a second, and without knowing how long your connections keep to open, do their thing, close, and get recycled, I suspect that this is just a problem you're going to have. One thing you can do is catch the BindException in your try block, use that to do anything you need to do in the bind-unsuccessful case, and wrap the whole call in a while loop that depends on a flag indicating whether the bind succeeded. Off the top of my head:
boolean hasBound = false;
while (!hasBound) {
try {
hasBound = true;
responseCode = httpClient.executeMethod(get);
} catch (BindException e) {
// do anything you want in the bound-unsuccessful case
} catch (final IOException e) {
...
}
}
Update with question: One curious question: what are the maximum total and per-host number of connections allowed by your MultiThreadedHttpConnectionManager? In your code, that'd be:
CONN_MGR.getParams().getDefaultMaxConnectionsPerHost();
CONN_MGR.getParams().getMaxTotalConnections();
Thus, you've fired more requests than TCP/IP ports are allowed to be opened. I don't do HttpClient, so I can't go in detail about this, but in theory there are three solutions for this particular problem:
Hardware based: add another NIC (network interface card).
Software based: close connections directly after use and/or increase the connection timeout.
Platform based: increase the amount of TCP/IP ports which are allowed to be opened. May be OS-specific and/or NIC driver-specific. The absolute maximum is 65535, of which several may already be reserved/in use (e.g. port 80).
So it turns out the problem was that one of the other HttpClient instances accidentally wasn't using the MultiThreadedHttpConnectionManager I instantiated, so I effectively had no rate limiting at all. Fixing this problem fixed the exception being thrown.
Thanks for all the suggestions, though!
Even though we invoke HttpClientUtils.closeQuietly(client); but in your code in case trying to read the content from HttpResponse entity like InputStream contentStream = HttpResponse.getEntity().getContent(), then you should close the inputstream also then only HttpClient connection get closed properly.