I have a larger block of Java code, but the important lines are these:
public static String tcp(String hostName, Number port, Number connectionTimeOutMs, Number readTimeOutMs, String message) {
String errmsg = "";
try (
Socket socket = new Socket();
) {
Inet4Address address = (Inet4Address) Inet4Address.getByName(hostName);
System.out.println("IP address:" + address.getHostAddress());
socket.connect(new InetSocketAddress(address, port.intValue()), connectionTimeOutMs.intValue());
socket.setSoTimeout(readTimeOutMs.intValue());
When I supply an IP address in the form "45.79.112.203"
or "tcpbin.com"
, the code gives a SocketTimeoutException
.
In the latter case, the line
System.out.println("IP address:" + address.getHostAddress());
gives the correct IP address, so the hostname is resolved correctly; it matches what ping tcpbin.com
returns.
I want to be able to call the function with either an IPv4 address (in String format) or a hostname.
What am I doing wrong? Why does the socket fail to establish a connection, even with a high timeout of 60,000 ms?
Notes:
tcpbin.com
is an "echo" server to test socket connections. It is only used as an example and should not be the cause of the problem.
Try the following:
echo "Text to send to TCP" | nc tcpbin.com 4242
You should get back the string that was just sent.
In the tcp() function, I pass in numbers in the form of a Number
object, since the Java code gets called from Karate test framework via Java inter-op and JavaScript. JavaScript has the type Number
, but no int
or double
.
===
Update:
Here a simple tcp server TcpServer.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
System.out.println("Listening on port 4242");
ServerSocket listener = null;
try {
do {
listener = new ServerSocket(4242);
Socket other = listener.accept();
System.out.println(">>> got a new connection from "
+ other.getInetAddress().toString() + " <<<");
other.getOutputStream().write("Blah blah".getBytes());
other.close();
listener.close();
} while (true);
} catch (IOException e) {
e.printStackTrace();
}
}
}
===
Here a test class to test the tcp()
function. It is the connect() statement that times out in case host != localhost.
TestTcpFunction.java:
import java.io.*;
import java.net.*;
public class TestTcpFunction {
public static void main(String[] args) {
String sendMessage = "Blah blah";
String host = (args.length==0)
? "localhost"
: "tcpbin.com";
String result = tcp(host, 4242, 30000, 30000, sendMessage);
System.out.println("result = " + result);
System.out.println("matches = " + result.equals(sendMessage));
}
public static String tcp(String hostName, Number port, Number connectionTimeOutMs, Number readTimeOutMs, String message) {
String errmsg = "";
try (
Socket socket = new Socket();
) {
Inet4Address address = (Inet4Address) Inet4Address.getByName(hostName);
System.out.println("trying to connect to:" + address.getHostAddress());
socket.connect(new InetSocketAddress(address, port.intValue()), connectionTimeOutMs.intValue()); // <<< times out if not localhost
socket.setSoTimeout(readTimeOutMs.intValue());
try (
PrintWriter out = new PrintWriter(socket.getOutputStream(), true); // autoflush
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
) {
out.print(message);
StringBuilder sb = new StringBuilder();
String line;
boolean addNewline = false;
while ((line = in.readLine()) != null) {
if (addNewline)
sb.append('\n');
sb.append(line);
if (line.lastIndexOf("</response>") >= 0)
break;
addNewline = true;
}
return sb.toString(); // The xml may not be well formed, for instance missing </response>
} finally {}
} catch (UnknownHostException e) {
errmsg = "Unknown host " + hostName;
} catch (SocketTimeoutException e) {
errmsg = "Socket connection timeout (before connection got established)";
} catch (SocketException e) {
errmsg = "Socket error: " + e.getMessage();
} catch (IOException e) {
errmsg = "Couldn't get I/O for the connection to " + hostName;
} catch (Exception e) {
errmsg = "Unknown socket error " + e.getMessage();
}
System.err.println(errmsg);
return "<Error> function tcp (Utils.java): " + errmsg + "</Error>";
}
}
===
Compile both with javac. Then start the server with java TcpServer
.
Next run java TestTcpFunction
in a different shell, without parameters.
The first time (with local host) it should work correctly.
Then run again, but with any parameter(s), like java TestTcpFunction 1
This time I get a timeout while trying to connect.
The code has been build and tested on my machine.