joanlofe joanlofe - 13 days ago 5
Java Question

java.net.Socket constructor throws Socket exception if using 4 parameter version but not with 2 parameter version

Playing a bit with sockets I've found the following issue. This program:

public class TestSocket {

private static final String remoteHost = "gmail-smtp-in.l.google.com";
private static final int port = 25;

public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("Remote: " + InetAddress.getByName(remoteHost));
System.out.println("Local: " + InetAddress.getByName("localhost"));

Socket socket = new Socket(InetAddress.getByName(remoteHost), port, InetAddress.getByName("localhost"), 0);


OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(out);
System.out.println("Server --> " + reader.readLine());
pw.println("helo localhost");
System.out.println("Sent 'helo localhost'");
socket.close();
}

}


throws the exception
java.net.SocketException: Network is unreachable: connect
in the line with the socket constructor. However, after trying with telnet and also netcat I have verified that the server is reachable and sends data. So it is a problem with the constructor. When I change it to the following the program works and is able to connect:

Socket socket = new Socket(InetAddress.getByName(remoteHost), port);


I cannot understand what is making the difference. Is not this second constructor also supposed to bind to an ephemeral port on localhost, like the first when when passed 0 as port? Why one works and the other do not?

Edit: using Java 1.8.0_112 on Windows 10.

Answer

public Socket(InetAddress host, int port, InetAddress interface, int localPort) throws IOException

This socket connects to the host and port specified in the first two arguments. It connects from the local network interface and port specified by the last two arguments.

So, what you're trying is to connect to a public address from your localhost, which doesn't make sense at all. The last 2 arguments of this constructor asks for picking a local interface to connect from.


Use-case explained for choosing this way of Socket creation:

Suppose you were writing a program to periodically dump error logs to a printer or send them over an internal mail server. You’d want to make sure you used the inward-facing network interface instead of the outward-facing network interface. So, in such cases you'd select this way of constructing socket.

Comments