| Avoid APIs that convert a hostname to a single IP address: |
| |
| * [`java.net.Socket(String,int)`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/Socket.html#%3Cinit%3E\(java.lang.String,int,boolean\)) |
| * [`java.net.InetSocketAddress(String,int)`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/InetSocketAddress.html#%3Cinit%3E\(java.lang.String,int\)) |
| * [`java.net.InetAddress.html#getByName(String)`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/InetAddress.html#getByName\(java.lang.String\)) |
| |
| Depending on the value of the |
| [`-Djava.net.preferIPv6Addresses=true`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/doc-files/net-properties.html) |
| system property, those APIs will return an IPv4 or IPv6 address. If a client |
| only has IPv4 connectivity, it will fail to connect with |
| `-Djava.net.preferIPv6Addresses=true`. If a client only has IPv6 connectivity, |
| it will fail to connect with `-Djava.net.preferIPv6Addresses=false`. |
| |
| The preferred alternative is for clients to consider all addresses returned by |
| [`java.net.InetAddress.html#getAllByName(String)`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/InetAddress.html#getAllByName\(java.lang.String\)), |
| and try to connect to each one until a successful connection is made. |
| |
| TIP: To resolve a loopback address, prefer `InetAddress.getLoopbackAddress()` |
| over hard-coding an IPv4 or IPv6 loopback address with |
| `InetAddress.getByName("127.0.0.1")` or `InetAddress.getByName("::1")`. |
| |
| This is, prefer this: |
| |
| ```java |
| Socket doConnect(String hostname, int port) throws IOException { |
| IOException exception = null; |
| for (InetAddress address : InetAddress.getAllByName(hostname)) { |
| try { |
| return new Socket(address, port); |
| } catch (IOException e) { |
| if (exception == null) { |
| exception = e; |
| } else { |
| exception.addSuppressed(e); |
| } |
| } |
| } |
| throw exception; |
| } |
| ``` |
| |
| ```java |
| Socket doConnect(String hostname, int port) throws IOException { |
| IOException exception = null; |
| for (InetAddress address : InetAddress.getAllByName(hostname)) { |
| try { |
| Socket s = new Socket(); |
| s.connect(new InetSocketAddress(address, port)); |
| return s; |
| } catch (IOException e) { |
| if (exception == null) { |
| exception = e; |
| } else { |
| exception.addSuppressed(e); |
| } |
| } |
| } |
| throw exception; |
| } |
| ``` |
| |
| instead of this: |
| |
| ```java |
| Socket doConnect(String hostname, int port) throws IOException { |
| return new Socket(hostname, port); |
| } |
| ``` |
| |
| ```java |
| void doConnect(String hostname, int port) throws IOException { |
| Socket s = new Socket(); |
| s.connect(new InetSocketAddress(hostname, port)); |
| } |
| ``` |
| |
| ```java |
| void doConnect(String hostname, int port) throws IOException { |
| Socket s = new Socket(); |
| s.connect(new InetSocketAddress(InetAddress.getByName(hostname), port)); |
| } |
| ``` |