1 /* 2 * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.net; 26 27 import java.io.ObjectInputStream; 28 import java.io.IOException; 29 import java.io.InvalidObjectException; 30 31 /** 32 * 33 * This class implements an IP Socket Address (IP address + port number) 34 * It can also be a pair (hostname + port number), in which case an attempt 35 * will be made to resolve the hostname. If resolution fails then the address 36 * is said to be <I>unresolved</I> but can still be used on some circumstances 37 * like connecting through a proxy. 38 * <p> 39 * It provides an immutable object used by sockets for binding, connecting, or 40 * as returned values. 41 * <p> 42 * The <i>wildcard</i> is a special local IP address. It usually means "any" 43 * and can only be used for <code>bind</code> operations. 44 * 45 * @see java.net.Socket 46 * @see java.net.ServerSocket 47 * @since 1.4 48 */ 49 public class InetSocketAddress extends SocketAddress { 50 /* The hostname of the Socket Address 51 * @serial 52 */ 53 private String hostname = null; 54 /* The IP address of the Socket Address 55 * @serial 56 */ 57 private InetAddress addr = null; 58 /* The port number of the Socket Address 59 * @serial 60 */ 61 private int port; 62 63 private static final long serialVersionUID = 5076001401234631237L; 64 65 private InetSocketAddress() { 66 } 67 68 /** 69 * Creates a socket address where the IP address is the wildcard address 70 * and the port number a specified value. 71 * <p> 72 * A valid port value is between 0 and 65535. 73 * A port number of <code>zero</code> will let the system pick up an 74 * ephemeral port in a <code>bind</code> operation. 75 * <p> 76 * @param port The port number 77 * @throws IllegalArgumentException if the port parameter is outside the specified 78 * range of valid port values. 79 */ 80 public InetSocketAddress(int port) { 81 this(InetAddress.anyLocalAddress(), port); 82 } 83 84 /** 85 * 86 * Creates a socket address from an IP address and a port number. 87 * <p> 88 * A valid port value is between 0 and 65535. 89 * A port number of <code>zero</code> will let the system pick up an 90 * ephemeral port in a <code>bind</code> operation. 91 * <P> 92 * A <code>null</code> address will assign the <i>wildcard</i> address. 93 * <p> 94 * @param addr The IP address 95 * @param port The port number 96 * @throws IllegalArgumentException if the port parameter is outside the specified 97 * range of valid port values. 98 */ 99 public InetSocketAddress(InetAddress addr, int port) { 100 if (port < 0 || port > 0xFFFF) { 101 throw new IllegalArgumentException("port out of range:" + port); 102 } 103 this.port = port; 104 if (addr == null) 105 this.addr = InetAddress.anyLocalAddress(); 106 else 107 this.addr = addr; 108 } 109 110 /** 111 * 112 * Creates a socket address from a hostname and a port number. 113 * <p> 114 * An attempt will be made to resolve the hostname into an InetAddress. 115 * If that attempt fails, the address will be flagged as <I>unresolved</I>. 116 * <p> 117 * If there is a security manager, its <code>checkConnect</code> method 118 * is called with the host name as its argument to check the permissiom 119 * to resolve it. This could result in a SecurityException. 120 * <P> 121 * A valid port value is between 0 and 65535. 122 * A port number of <code>zero</code> will let the system pick up an 123 * ephemeral port in a <code>bind</code> operation. 124 * <P> 125 * @param hostname the Host name 126 * @param port The port number 127 * @throws IllegalArgumentException if the port parameter is outside the range 128 * of valid port values, or if the hostname parameter is <TT>null</TT>. 129 * @throws SecurityException if a security manager is present and 130 * permission to resolve the host name is 131 * denied. 132 * @see #isUnresolved() 133 */ 134 public InetSocketAddress(String hostname, int port) { 135 if (port < 0 || port > 0xFFFF) { 136 throw new IllegalArgumentException("port out of range:" + port); 137 } 138 if (hostname == null) { 139 throw new IllegalArgumentException("hostname can't be null"); 140 } 141 try { 142 addr = InetAddress.getByName(hostname); 143 } catch(UnknownHostException e) { 144 this.hostname = hostname; 145 addr = null; 146 } 147 this.port = port; 148 } 149 150 /** 151 * 152 * Creates an unresolved socket address from a hostname and a port number. 153 * <p> 154 * No attempt will be made to resolve the hostname into an InetAddress. 155 * The address will be flagged as <I>unresolved</I>. 156 * <p> 157 * A valid port value is between 0 and 65535. 158 * A port number of <code>zero</code> will let the system pick up an 159 * ephemeral port in a <code>bind</code> operation. 160 * <P> 161 * @param host the Host name 162 * @param port The port number 163 * @throws IllegalArgumentException if the port parameter is outside 164 * the range of valid port values, or if the hostname 165 * parameter is <TT>null</TT>. 166 * @see #isUnresolved() 167 * @return a <code>InetSocketAddress</code> representing the unresolved 168 * socket address 169 * @since 1.5 170 */ 171 public static InetSocketAddress createUnresolved(String host, int port) { 172 if (port < 0 || port > 0xFFFF) { 173 throw new IllegalArgumentException("port out of range:" + port); 174 } 175 if (host == null) { 176 throw new IllegalArgumentException("hostname can't be null"); 177 } 178 InetSocketAddress s = new InetSocketAddress(); 179 s.port = port; 180 s.hostname = host; 181 s.addr = null; 182 return s; 183 } 184 185 private void readObject(ObjectInputStream s) 186 throws IOException, ClassNotFoundException { 187 s.defaultReadObject(); 188 189 // Check that our invariants are satisfied 190 if (port < 0 || port > 0xFFFF) { 191 throw new InvalidObjectException("port out of range:" + port); 192 } 193 194 if (hostname == null && addr == null) { 195 throw new InvalidObjectException("hostname and addr " + 196 "can't both be null"); 197 } 198 } 199 200 /** 201 * Gets the port number. 202 * 203 * @return the port number. 204 */ 205 public final int getPort() { 206 return port; 207 } 208 209 /** 210 * 211 * Gets the <code>InetAddress</code>. 212 * 213 * @return the InetAdress or <code>null</code> if it is unresolved. 214 */ 215 public final InetAddress getAddress() { 216 return addr; 217 } 218 219 /** 220 * Gets the <code>hostname</code>. 221 * Note: This method may trigger a name service reverse lookup if the 222 * address was created with a literal IP address. 223 * 224 * @return the hostname part of the address. 225 */ 226 public final String getHostName() { 227 if (hostname != null) 228 return hostname; 229 if (addr != null) 230 return addr.getHostName(); 231 return null; 232 } 233 234 /** 235 * Returns the hostname, or the String form of the address if it 236 * doesn't have a hostname (it was created using a literal). 237 * This has the benefit of <b>not</b> attemptimg a reverse lookup. 238 * 239 * @return the hostname, or String representation of the address. 240 * @since 1.7 241 */ 242 public final String getHostString() { 243 if (hostname != null) 244 return hostname; 245 if (addr != null) { 246 if (addr.hostName != null) 247 return addr.hostName; 248 else 249 return addr.getHostAddress(); 250 } 251 return null; 252 } 253 254 /** 255 * Checks whether the address has been resolved or not. 256 * 257 * @return <code>true</code> if the hostname couldn't be resolved into 258 * an <code>InetAddress</code>. 259 */ 260 public final boolean isUnresolved() { 261 return addr == null; 262 } 263 264 /** 265 * Constructs a string representation of this InetSocketAddress. 266 * This String is constructed by calling toString() on the InetAddress 267 * and concatenating the port number (with a colon). If the address 268 * is unresolved then the part before the colon will only contain the hostname. 269 * 270 * @return a string representation of this object. 271 */ 272 public String toString() { 273 if (isUnresolved()) { 274 return hostname + ":" + port; 275 } else { 276 return addr.toString() + ":" + port; 277 } 278 } 279 280 /** 281 * Compares this object against the specified object. 282 * The result is <code>true</code> if and only if the argument is 283 * not <code>null</code> and it represents the same address as 284 * this object. 285 * <p> 286 * Two instances of <code>InetSocketAddress</code> represent the same 287 * address if both the InetAddresses (or hostnames if it is unresolved) and port 288 * numbers are equal. 289 * If both addresses are unresolved, then the hostname & the port number 290 * are compared. 291 * 292 * Note: Hostnames are case insensitive. e.g. "FooBar" and "foobar" are 293 * considered equal. 294 * 295 * @param obj the object to compare against. 296 * @return <code>true</code> if the objects are the same; 297 * <code>false</code> otherwise. 298 * @see java.net.InetAddress#equals(java.lang.Object) 299 */ 300 public final boolean equals(Object obj) { 301 if (obj == null || !(obj instanceof InetSocketAddress)) 302 return false; 303 InetSocketAddress sockAddr = (InetSocketAddress) obj; 304 boolean sameIP = false; 305 if (this.addr != null) 306 sameIP = this.addr.equals(sockAddr.addr); 307 else if (this.hostname != null) 308 sameIP = (sockAddr.addr == null) && 309 this.hostname.equalsIgnoreCase(sockAddr.hostname); 310 else 311 sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null); 312 return sameIP && (this.port == sockAddr.port); 313 } 314 315 /** 316 * Returns a hashcode for this socket address. 317 * 318 * @return a hash code value for this socket address. 319 */ 320 public final int hashCode() { 321 if (addr != null) 322 return addr.hashCode() + port; 323 if (hostname != null) 324 return hostname.toLowerCase().hashCode() + port; 325 return port; 326 } 327 }