As part of an ongoing saga to get my app approved by the Apple review team, I have come up against another road block.
As the title suggests, when calling InetAddress.getAllByName("https://artatlas.io") an UnknownHostException is thrown. This only happens during their testing process. When I test my app on my local NAT64 network (as suggested by Apple); the error never occurs, and the app works as intended.
The code I am running:
System.setProperty("java.net.preferIPv6Addresses", "true");
System.setProperty("networkaddress.cache.negative.ttl", "0");
InetAddress[] addrs;
try {
addrs = InetAddress.getAllByName("https://artatlas.io");
String addresses = "";
for(InetAddress addr: addrs){
addresses += addr + "\n";
}
System.out.println("Addresses: " + addresses + "\n");
} catch (IOException e1) {
e1.printStackTrace();
}
What I've discovered is, anything I append with "https://" seems to return the same, single IP address:
Addresses: https://artatlas.io/122.150.5.20
Addresses: https://google.com/122.150.5.20
Addresses: https://www.google.com/122.150.5.20
I could just get rid of the https, but then I'm concerned my later use of a HttpsURLConnection will fail (my connection MUST be https)
testUrl = new URL("https://artatlas.io");
testConn = (HttpsURLConnection) testUrl.openConnection();
I know that a HttpsURLConnection uses an InetAddress instance to form its connection, so the question is what process does it use to parse the URL string, does it remove the protocol? What's the correct approach here?
The hostname shouldn't include a protocol. The host is the same, no matter what protocol you intend to use with it. Whether the later HTTPS connection fails or not, InetAddress.getAllByName() is unrelated to it (it doesn't and can't guarantee success or failure).
You're dealing with DNS only at this point, so it's just foo.com or 123.45.67.89 or an IPv6 address.
Related
How would you get the domain name of from a TCP connection?
As I'm trying to make a proxy type software but it must detect what the domain is and then go where it needs to. However I'm unsure how to get the domain name from the client.
There is no general way to get the target domain or host name from of the TCP connection, because a connection is only defined by its target IP address and not the host name and there might be several names for a single target IP address. But while there is no general way to get the target name from all TCP connections it is possible with some protocols on top of HTTP:
In case of HTTP you might look at the HTTP Host header which contains the target host name and is set by nearly all HTTP stacks (required with HTTP/1.1).
With SSL you might try to extract the host name from the initial ClientHello message in the SSL handshake, in case the client uses SNI (server name indication). All modern browsers use SNI, but older browser like IE8 not and also not older Java, Python, Perl, Ruby ... applications.
You may use the following code snippet which will give local domain name -
try {
InetAddress me = InetAddress.getLocalHost();
String dottedQuad = me.getHostAddress();
System.out.println("My address is " + dottedQuad);
} catch (UnknownHostException e) {
System.out.println("I'm sorry. I don't know my own address.");
}
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
I wrote a method which will help us finding whether the system using the proxy to connect with internet which is as follows,
try {
System.out.println("Checking internet connection availability.....");
URL u = new URL("http://www.google.com/");
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
uc.setReadTimeout(1);//I have tried this without timeout and with it too. But it didnt work
System.out.println(uc.getResponseCode());
} catch (Exception ex) {
System.out.println("Unable to connect to internet without proxy.....");
System.out.println("Checking for any proxy settings from the PC");
System.setProperty("java.net.useSystemProxies", "true");
try {
System.setProperty("java.net.useSystemProxies", "true");
URL u = new URL("http://www.google.com/");
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
System.out.println(uc.getResponseCode());
System.out.println("Internet connection available");
} catch (Exception e) {
System.out.println("Internet connection not available :(");
}
}
Initially, I am trying to open the URL connection without proxy (assuming the system don't have proxy to connect with internet).I have set the timeout to 1 ms. Trying to get the response code from the site.
If any error occurs means (like timeout), then in the catch block i am trying to connect to internet with system's proxy, by means of setting the useSystemProxies to true.
But even after that also, I am not able to get the response from the site.
I am using a system with proxy settings.
I have tried the following too in the catch block
Proxy next = ProxySelector.getDefault().select(new URI("http://www.google.com/")).iterator().next();
if (next.address() != null) {
System.out.println("Detecting Proxy configurations.....");
String proxy = next.address().toString();
String proxyHost = proxy.substring(0, proxy.indexOf(":"));
String proxyPort = proxy.substring(proxy.indexOf(":") + 1);
System.out.println("Proxy Configuration : " + proxyHost + " # " + proxyPort);
}
The above block of code also is not working. Can anyone help me out with this?
InetAddress.isReachable
Test whether that address is reachable. Best effort is made by the
implementation to try to reach the host, but firewalls and server
configuration may block requests resulting in a unreachable status
while some specific ports may be accessible. A typical implementation
will use ICMP ECHO REQUESTs if the privilege can be obtained,
otherwise it will try to establish a TCP connection on port 7 (Echo)
of the destination host. The timeout value, in milliseconds, indicates
the maximum amount of time the try should take. If the operation times
out before getting an answer, the host is deemed unreachable. A
negative value will result in an IllegalArgumentException being
thrown.
In your first code snippet in the catch block try setting the following codes.
System.setProperty("http.proxyHost", "Proxy host");
System.setProperty("http.proxyPort", "Proxy Port");
Seems like your proxy is registered as system proxy and not visible to the JVM.
I'm making a client/server pair with sockets to send and receive data back and forth. When I'm at home on my internet using two separate machines for client/server, it works fine as expected. Data is transmitted and so forth.
However, today when I was working at a local coffee shop (Second Cup, in case that's relevant), this did not work. I kept getting the following errors: either connection timed out, or no route to host.
Here is the relevant code:
Server:
public class TestServer {
public static void main(String[] args) throws Exception {
TestServer myServer = new TestServer();
myServer.run();
}
private void run() throws Exception {
ServerSocket mySS = new ServerSocket(9999);
while(true) {
Socket SS_accept = mySS.accept();
BufferedReader myBR = new BufferedReader(new InputStreamReader(SS_accept.getInputStream()));
String temp = myBR.readLine();
System.out.println(temp);
if (temp!=null) {
PrintStream serverPS = new PrintStream(SS_accept.getOutputStream());
serverPS.println("Response received");
}
}
}
}
Client: (the relevant part)
//sends a command to the server, and returns the server's response
private String tellServer(String text) throws Exception {
mySocket = new Socket("192.168.0.XXX", 9999); //the IPv4 address
//use the socket's outputStream to tell stuff to the server
PrintStream myPS = new PrintStream(mySocket.getOutputStream());
myPS.println(text);
//the following code will get data back from the server
BufferedReader clientBR = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
String temp = clientBR.readLine();
if (temp!=null) {
return temp;
} else {
return "";
}
}
It's pretty much as simple as can be. Again, as mentioned, at home on my internet it works fine - just do ipconfig, grab the IPv4 address, and put it in for the client. In coffee shops with free wifi, it doesn't work. I even fiddled with many different ports just in case.
Thanks for any help, I'm new to sockets and finding this confusing.
192.168.x.y is a local address. source
You need your home machines ip address as the INTERNET sees it.
When you're home next, go to http://www.whatismyip.com/ and see what it thinks you are.
Note that you might need to go onto your router and route traffic from your router to your machine for port 9999, since that's what you'll probably be hitting.
When you're running both the server and client on the same machine, you could use the loopback address, 127.0.0.1, when out at the coffee shop.
Using the loopback address and running the server and client on the one machine should work all the time, whether at home or out.
You could check your IP address as suggested by Total, but that will only stay the same if you have a static IP. If you aren't sure if you have a static or dynamic IP address, you probably have a dynamic IP address but you should check your IP address a few times over a week or so to observe any change.
Another alternative is to consider a free dns server e.g. http://freedns.afraid.org/ , set a job to update your IP address regularly with that service and use whatever domain name you have chosen to access your local server.
With either method of accessing your home network remotely, you'll need to forward traffic on 9999 to the relevant machine on your home network.
HTH :)
Because I didn't want to implement a communication protocol for my client-server based application, I implemented a RMI client and a RMI server on both sides for the information exchange between the two components.
If I try to use my application by starting the two components on the same machine, everything is working fine. But if I split the components to two different computers (Kubuntu 9.04 within as a virtual machine within an Windows 7 RC environment with disabled firewall and a native Ubuntu 9.04 environment), it seems like the RMI client is not able to execute the methods which are defined on the server side. (Every functions call leads to a RMI exception.)
Currently I only set the system property "java.rmi.server.hostname" on both sides to the network interface which should be used for the data exchange and registered the default port for the communication with rmi daemon (?) rmid.
Does somebody has an idea what might be going wrong? Do I have to set some other parameters like "java.rmi.server.codebase" (http://java.sun.com/j2se/1.4.2/docs/guide/rmi/javarmiproperties.html) to be able to use the RMI functionality within my application?
Edit: Okay, here is some additional information for you:
In the initialization phase my client tries to establish a connection to the RMI server of server component, which was initialized using the following two methods:
private void initialize()
{
// set ip address of rmi server
System.setProperty("java.rmi.server.hostname", ipAddress);
// try to register rmi server
try
{
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
}
catch (Exception e)
{
// ignore
}
}
public void start()
{
System.out.print("starting master control RMI server ...");
try
{
Naming.rebind("MasterControl", this);
}
catch (Exception e)
{
System.out.println("error: could not initialize master control RMI server");
System.exit(1);
}
// set running flag
isRunning = true;
System.out.println(" done");
}
"ipAddress" is here the ip address of the network interface of the server component.
The method which is used by the client component to establish the connection looks like this:
public void connect()
{
// build connection url
String url = "rmi://" + masterControlIpAddress + "/MasterControl";
System.out.println(url);
System.out.print("connecting to master control ...");
// try to connect to master control server
while (connection == null)
{
try
{
connection = (MasterControlInterface) Naming.lookup(url);
id = connection.register(localIpAddress);
}
catch (Exception e)
{
// ignore
}
if (connection == null)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
System.out.println(" done");
}
As you can see my client calls a function to register the connection at the server:
#Override
public int register(String ipAddress) throws RemoteException
{
// add connection to registrationHandler
masterControl.registrationHandler.addConnection(ipAddress);
// log
int connectionCount = masterControl.registrationHandler.getConnectionCount();
System.out.println("slave control (" + ipAddress + ") instance has been registered at the master control server under the following id: " + connectionCount);
return connectionCount;
}
If I run my program using a real network connection, the text "slave control ..." is not displayed on the server side. Therefore I'm not sure, if the function is really called by the client component.
After the client component is intialized it tries to notify the server component by calling the following method using it's RMI connection to the server:
public void sendInitializationDone()
{
try
{
connection.initializationDone();
}
catch (RemoteException e)
{
System.out.println("error: could not send 'initializationDone' message to master control");
System.out.println(e);
System.exit(1);
}
}
to set a flag on the server side.
The error occures inside this function on the client side:
java.rmi.ConnectException: Connection refused to host 127.0.1.1; nested exception is: java.net.ConnectException: Connection refused.
I have no idea why the host is here 127.0.1.1 ...
#nos
Of course, I disabled the windows firewall and the protection mechanismn of Kaspersky Internet Security. I don't think that there is a running firewall in my Kubuntu. In generell it is possible to establish a connection, because I already used scp to copy my program to the other machine.
Edit2:
Mhhh, after setting the entry in /etc/hosts which refers to the machine to the ip address of the machine it seems to work, but don't really understand why it does ...
BR,
Markus
You need to add an entry to the hosts file of the machines containing an entry of the form
machinename privateip
e.g.
virtualmachine 192.168.1.16
This will prevent RMI from sending the localhost host name as a 'call me back' address.
To test this approach, run the following code before and after performing the change.
System.out.println(java.net.InetAddress.getLocalHost());
It should output a local address before the changes and a non-local address after the changes.
Using different versions of the JDK on each server could cause this problem.
Use the
java -version
command to make sure that you are using the same version of the jre.