我有一个更大的java代码块,但重要的一行是:
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());
当我在表单中提供ip地址时 "45.79.112.203"
或者 "tcpbin.com"
,代码给出 SocketTimeoutException
.
在后一种情况下
System.out.println("IP address:" + address.getHostAddress());
提供正确的ip地址,以便正确解析主机名;匹配什么 ping tcpbin.com
返回。
我希望能够使用ipv4地址(字符串格式)或主机名调用函数。
我做错什么了?为什么即使有60000毫秒的高超时,套接字也无法建立连接?
笔记: tcpbin.com
是一个“echo”服务器,用于测试套接字连接。它仅用作示例,不应成为问题的原因。
请尝试以下操作:
echo "Text to send to TCP" | nc tcpbin.com 4242
你应该拿回刚才发来的那条线。
在tcp()函数中,我以 Number
对象,因为java代码是通过java inter-op和javascript从空手道测试框架调用的。javascript的类型 Number
,但不是 int
或者 double
.
更新:
这里是一个简单的tcp服务器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();
}
}
}
===
这里有一个测试类来测试 tcp()
功能。如果host!=本地主机。
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>";
}
}
===
用javac编译两者。然后用启动服务器 java TcpServer
. 下次跑步 java TestTcpFunction
在不同的shell中,没有参数。
第一次(与本地主机)它应该正常工作。然后再次运行,但使用任何参数,如 java TestTcpFunction 1
这次我尝试连接时超时。
代码已经在我的机器上构建和测试。
1条答案
按热度按时间wbgh16ku1#
客户端在connect中未超时。一个简单的输出
connect
显示连接实际上已成功:相反,程序在从服务器读取时挂起。对于当前代码,它将等待服务器关闭连接或发送一条带有
</response>
. 但是服务器tcpbin。com:4242 will 不要做这种事。它只会读取任何内容并将其回显。得到一个</response>
字符串一实际上必须发送这个字符串-这还没有完成。因此,根据设置的超时,读取将在一段时间后超时
socket.setSoTimeout
. 结果SocketTimeoutException
错误地解释为连接超时,但它是读取超时。假设代码期望回显消息包含字符串
</response>
必须将其添加到已发送的消息中:但这仍然不够,tcpdump显示消息甚至没有被发送。这是因为期望
out.print(message);
受autoflush影响是完全错误的-请看我创建了一个带有autoflush的printwriter;为什么不是自动冲洗?。因此,必须明确地刷新写入程序:tcpdump显示消息现在实际上已发送,但没有任何回显。这是因为echo服务器实际上希望读取行,但尚未发送行结束。添加它实际上有助于发送消息、获得回显消息并打破循环:
为什么要用localhost呢?因为示例服务器的行为实际上与tcpbin.com上的echo服务器不同。它没有读取任何内容,只是发送了一条固定消息并关闭了连接。