稍微使用一下套接字,我发现了以下问题。该程序:
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();
}
}
在套接字构造函数所在行中抛出异常java.net.SocketException: Network is unreachable: connect
。然而,在尝试使用 telnet 和 netcat 之后,我已经验证服务器可以访问并发送数据。所以这是构造函数的问题。当我将其更改为以下内容时,程序可以正常工作并能够连接:
Socket socket = new Socket(InetAddress.getByName(remoteHost), port);
我不明白是什么造成了这种差异。难道第二个构造函数不是也应该绑定(bind)到本地主机上的临时端口,就像第一个构造函数传递 0 作为端口时一样吗?为什么一个有效而另一个无效?
编辑:在 Windows 10 上使用 Java 1.8.0_112。
最佳答案
public Socket(InetAddress host, int port, InetAddress interface, int localPort) throws IOException
此套接字连接到前两个参数中指定的主机和端口。它从最后两个参数指定的本地网络接口(interface)和端口进行连接。
因此,您尝试的是从本地主机连接到公共(public)地址,这根本没有意义。此构造函数的最后 2 个参数要求选择一个本地接口(interface)进行连接。
<小时/>选择这种套接字创建方式的用例解释:
假设您正在编写一个程序来定期将错误日志转储到打印机或通过内部邮件服务器发送它们。您需要确保使用向内的网络接口(interface)而不是向外的网络接口(interface)。因此,在这种情况下,您应该选择这种构造套接字的方式。
关于如果使用 4 参数版本但不使用 2 参数版本,java.net.Socket 构造函数会抛出 Socket 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40708505/