1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.net; 19 20 import java.io.IOException; 21 import java.io.ObjectInputStream; 22 23 /** 24 * This class represents a socket endpoint described by a IP address and a port 25 * number. It is a concrete implementation of {@code SocketAddress} for IP. 26 */ 27 public class InetSocketAddress extends SocketAddress { 28 29 private static final long serialVersionUID = 5076001401234631237L; 30 31 // Exactly one of hostname or addr should be set. 32 private final InetAddress addr; 33 private final String hostname; 34 private final int port; 35 36 /** 37 * @hide internal use only 38 */ 39 public InetSocketAddress() { 40 // These will be filled in the native implementation of recvfrom. 41 this.addr = null; 42 this.hostname = null; 43 this.port = -1; 44 } 45 46 /** 47 * Creates a socket endpoint with the given port number {@code port} and 48 * no specified address. The range for valid port numbers is between 0 and 49 * 65535 inclusive. 50 * 51 * @param port 52 * the specified port number to which this socket is bound. 53 */ 54 public InetSocketAddress(int port) { 55 this((InetAddress) null, port); 56 } 57 58 /** 59 * Creates a socket endpoint with the given port number {@code port} and 60 * {@code address}. The range for valid port numbers is between 0 and 65535 61 * inclusive. If {@code address} is {@code null} this socket is bound to the 62 * IPv4 wildcard address. 63 * 64 * @param port 65 * the specified port number to which this socket is bound. 66 * @param address 67 * the specified address to which this socket is bound. 68 */ 69 public InetSocketAddress(InetAddress address, int port) { 70 if (port < 0 || port > 65535) { 71 throw new IllegalArgumentException("port=" + port); 72 } 73 this.addr = (address == null) ? Inet4Address.ANY : address; 74 this.hostname = null; 75 this.port = port; 76 } 77 78 /** 79 * Creates a socket endpoint with the given port number {@code port} and the 80 * hostname {@code host}. The hostname is tried to be resolved and cannot be 81 * {@code null}. The range for valid port numbers is between 0 and 65535 82 * inclusive. 83 * 84 * @param port 85 * the specified port number to which this socket is bound. 86 * @param host 87 * the specified hostname to which this socket is bound. 88 */ 89 public InetSocketAddress(String host, int port) { 90 this(host, port, true); 91 } 92 93 /* 94 * Internal constructor for InetSocketAddress(String, int) and 95 * createUnresolved(String, int); 96 */ 97 InetSocketAddress(String hostname, int port, boolean needResolved) { 98 if (hostname == null || port < 0 || port > 65535) { 99 throw new IllegalArgumentException("host=" + hostname + ", port=" + port); 100 } 101 102 InetAddress addr = null; 103 if (needResolved) { 104 try { 105 addr = InetAddress.getByName(hostname); 106 hostname = null; 107 } catch (UnknownHostException ignored) { 108 } 109 } 110 this.addr = addr; 111 this.hostname = hostname; 112 this.port = port; 113 } 114 115 /** 116 * Creates an {@code InetSocketAddress} without trying to resolve the 117 * hostname into an {@code InetAddress}. The address field is marked as 118 * unresolved. 119 * 120 * @param host 121 * the specified hostname to which this socket is bound. 122 * @param port 123 * the specified port number to which this socket is bound. 124 * @return the created InetSocketAddress instance. 125 * @throws IllegalArgumentException 126 * if the hostname {@code host} is {@code null} or the port is 127 * not in the range between 0 and 65535. 128 */ 129 public static InetSocketAddress createUnresolved(String host, int port) { 130 return new InetSocketAddress(host, port, false); 131 } 132 133 /** 134 * Gets the port number of this socket. 135 * 136 * @return the socket endpoint port number. 137 */ 138 public final int getPort() { 139 return port; 140 } 141 142 /** 143 * Gets the address of this socket. 144 * 145 * @return the socket endpoint address. 146 */ 147 public final InetAddress getAddress() { 148 return addr; 149 } 150 151 /** 152 * Returns the hostname, doing a reverse lookup on the {@code InetAddress} if no 153 * hostname string was provided at construction time. 154 */ 155 public final String getHostName() { 156 return (addr != null) ? addr.getHostName() : hostname; 157 } 158 159 /** 160 * Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}. 161 * Unlike {@link #getHostName}, this method will never cause a DNS lookup. 162 * @since 1.7 163 * @hide 1.7 - remember to add a link in the getHostName documentation! 164 */ 165 public final String getHostString() { 166 return (hostname != null) ? hostname : addr.getHostAddress(); 167 } 168 169 /** 170 * Returns whether this socket address is unresolved or not. 171 * 172 * @return {@code true} if this socket address is unresolved, {@code false} 173 * otherwise. 174 */ 175 public final boolean isUnresolved() { 176 return addr == null; 177 } 178 179 /** 180 * Returns a string containing the address (or the hostname for an 181 * unresolved {@code InetSocketAddress}) and port number. 182 * For example: {@code "www.google.com/74.125.224.115:80"} or {@code "/127.0.0.1:80"}. 183 */ 184 @Override public String toString() { 185 return ((addr != null) ? addr.toString() : hostname) + ":" + port; 186 } 187 188 /** 189 * Compares two socket endpoints and returns true if they are equal. Two 190 * socket endpoints are equal if the IP address or the hostname of both are 191 * equal and they are bound to the same port. 192 * 193 * @param socketAddr 194 * the object to be tested for equality. 195 * @return {@code true} if this socket and the given socket object {@code 196 * socketAddr} are equal, {@code false} otherwise. 197 */ 198 @Override 199 public final boolean equals(Object socketAddr) { 200 if (this == socketAddr) { 201 return true; 202 } 203 if (!(socketAddr instanceof InetSocketAddress)) { 204 return false; 205 } 206 InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr; 207 208 // check the ports as we always need to do this 209 if (port != iSockAddr.port) { 210 return false; 211 } 212 213 // we only use the hostnames in the comparison if the addrs were not 214 // resolved 215 if ((addr == null) && (iSockAddr.addr == null)) { 216 return hostname.equals(iSockAddr.hostname); 217 } 218 219 // addrs were resolved so use them for the comparison 220 if (addr == null) { 221 // if we are here we know iSockAddr is not null so just return 222 // false 223 return false; 224 } 225 return addr.equals(iSockAddr.addr); 226 } 227 228 @Override 229 public final int hashCode() { 230 if (addr == null) { 231 return hostname.hashCode() + port; 232 } 233 return addr.hashCode() + port; 234 } 235 236 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 237 stream.defaultReadObject(); 238 } 239 } 240