1. /*
  2. * @(#)InetSocketAddress.java 1.20 04/02/03
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.net;
  8. import java.io.ObjectInputStream;
  9. import java.io.IOException;
  10. import java.io.InvalidObjectException;
  11. /**
  12. *
  13. * This class implements an IP Socket Address (IP address + port number)
  14. * It can also be a pair (hostname + port number), in which case an attempt
  15. * will be made to resolve the hostname. If resolution fails then the address
  16. * is said to be <I>unresolved</I> but can still be used on some circumstances
  17. * like connecting through a proxy.
  18. * <p>
  19. * It provides an immutable object used by sockets for binding, connecting, or
  20. * as returned values.
  21. * <p>
  22. * The <i>wildcard</i> is a special local IP address. It usually means "any"
  23. * and can only be used for <code>bind</code> operations.
  24. *
  25. * @see java.net.Socket
  26. * @see java.net.ServerSocket
  27. * @since 1.4
  28. */
  29. public class InetSocketAddress extends SocketAddress {
  30. /* The hostname of the Socket Address
  31. * @serial
  32. */
  33. private String hostname = null;
  34. /* The IP address of the Socket Address
  35. * @serial
  36. */
  37. private InetAddress addr = null;
  38. /* The port number of the Socket Address
  39. * @serial
  40. */
  41. private int port;
  42. private static final long serialVersionUID = 5076001401234631237L;
  43. private InetSocketAddress() {
  44. }
  45. /**
  46. * Creates a socket address where the IP address is the wildcard address
  47. * and the port number a specified value.
  48. * <p>
  49. * A valid port value is between 0 and 65535.
  50. * A port number of <code>zero</code> will let the system pick up an
  51. * ephemeral port in a <code>bind</code> operation.
  52. * <p>
  53. * @param port The port number
  54. * @throws IllegalArgumentException if the port parameter is outside the specified
  55. * range of valid port values.
  56. */
  57. public InetSocketAddress(int port) {
  58. this(InetAddress.anyLocalAddress(), port);
  59. }
  60. /**
  61. *
  62. * Creates a socket address from an IP address and a port number.
  63. * <p>
  64. * A valid port value is between 0 and 65535.
  65. * A port number of <code>zero</code> will let the system pick up an
  66. * ephemeral port in a <code>bind</code> operation.
  67. * <P>
  68. * A <code>null</code> address will assign the <i>wildcard</i> address.
  69. * <p>
  70. * @param addr The IP address
  71. * @param port The port number
  72. * @throws IllegalArgumentException if the port parameter is outside the specified
  73. * range of valid port values.
  74. */
  75. public InetSocketAddress(InetAddress addr, int port) {
  76. if (port < 0 || port > 0xFFFF) {
  77. throw new IllegalArgumentException("port out of range:" + port);
  78. }
  79. this.port = port;
  80. if (addr == null)
  81. this.addr = InetAddress.anyLocalAddress();
  82. else
  83. this.addr = addr;
  84. }
  85. /**
  86. *
  87. * Creates a socket address from a hostname and a port number.
  88. * <p>
  89. * An attempt will be made to resolve the hostname into an InetAddress.
  90. * If that attempt fails, the address will be flagged as <I>unresolved</I>.
  91. * <p>
  92. * If there is a security manager, its <code>checkConnect</code> method
  93. * is called with the host name as its argument to check the permissiom
  94. * to resolve it. This could result in a SecurityException.
  95. * <P>
  96. * A valid port value is between 0 and 65535.
  97. * A port number of <code>zero</code> will let the system pick up an
  98. * ephemeral port in a <code>bind</code> operation.
  99. * <P>
  100. * @param hostname the Host name
  101. * @param port The port number
  102. * @throws IllegalArgumentException if the port parameter is outside the range
  103. * of valid port values, or if the hostname parameter is <TT>null</TT>.
  104. * @throws SecurityException if a security manager is present and
  105. * permission to resolve the host name is
  106. * denied.
  107. * @see #isUnresolved()
  108. */
  109. public InetSocketAddress(String hostname, int port) {
  110. if (port < 0 || port > 0xFFFF) {
  111. throw new IllegalArgumentException("port out of range:" + port);
  112. }
  113. if (hostname == null) {
  114. throw new IllegalArgumentException("hostname can't be null");
  115. }
  116. try {
  117. addr = InetAddress.getByName(hostname);
  118. } catch(UnknownHostException e) {
  119. this.hostname = hostname;
  120. addr = null;
  121. }
  122. this.port = port;
  123. }
  124. /**
  125. *
  126. * Creates an unresolved socket address from a hostname and a port number.
  127. * <p>
  128. * No attempt will be made to resolve the hostname into an InetAddress.
  129. * The address will be flagged as <I>unresolved</I>.
  130. * <p>
  131. * A valid port value is between 0 and 65535.
  132. * A port number of <code>zero</code> will let the system pick up an
  133. * ephemeral port in a <code>bind</code> operation.
  134. * <P>
  135. * @param host the Host name
  136. * @param port The port number
  137. * @throws IllegalArgumentException if the port parameter is outside
  138. * the range of valid port values, or if the hostname
  139. * parameter is <TT>null</TT>.
  140. * @see #isUnresolved()
  141. * @return a <code>InetSocketAddress</code> representing the unresolved
  142. * socket address
  143. * @since 1.5
  144. */
  145. public static InetSocketAddress createUnresolved(String host, int port) {
  146. if (port < 0 || port > 0xFFFF) {
  147. throw new IllegalArgumentException("port out of range:" + port);
  148. }
  149. if (host == null) {
  150. throw new IllegalArgumentException("hostname can't be null");
  151. }
  152. InetSocketAddress s = new InetSocketAddress();
  153. s.port = port;
  154. s.hostname = host;
  155. s.addr = null;
  156. return s;
  157. }
  158. private void readObject(ObjectInputStream s)
  159. throws IOException, ClassNotFoundException {
  160. s.defaultReadObject();
  161. // Check that our invariants are satisfied
  162. if (port < 0 || port > 0xFFFF) {
  163. throw new InvalidObjectException("port out of range:" + port);
  164. }
  165. if (hostname == null && addr == null) {
  166. throw new InvalidObjectException("hostname and addr " +
  167. "can't both be null");
  168. }
  169. }
  170. /**
  171. * Gets the port number.
  172. *
  173. * @return the port number.
  174. */
  175. public final int getPort() {
  176. return port;
  177. }
  178. /**
  179. *
  180. * Gets the <code>InetAddress</code>.
  181. *
  182. * @return the InetAdress or <code>null</code> if it is unresolved.
  183. */
  184. public final InetAddress getAddress() {
  185. return addr;
  186. }
  187. /**
  188. * Gets the <code>hostname</code>.
  189. *
  190. * @return the hostname part of the address.
  191. */
  192. public final String getHostName() {
  193. if (hostname != null)
  194. return hostname;
  195. if (addr != null)
  196. return addr.getHostName();
  197. return null;
  198. }
  199. /**
  200. * Checks whether the address has been resolved or not.
  201. *
  202. * @return <code>true</code> if the hostname couldn't be resolved into
  203. * an <code>InetAddress</code>.
  204. */
  205. public final boolean isUnresolved() {
  206. return addr == null;
  207. }
  208. /**
  209. * Constructs a string representation of this InetSocketAddress.
  210. * This String is constructed by calling toString() on the InetAddress
  211. * and concatenating the port number (with a colon). If the address
  212. * is unresolved then the part before the colon will only contain the hostname.
  213. *
  214. * @return a string representation of this object.
  215. */
  216. public String toString() {
  217. if (isUnresolved()) {
  218. return hostname + ":" + port;
  219. } else {
  220. return addr.toString() + ":" + port;
  221. }
  222. }
  223. /**
  224. * Compares this object against the specified object.
  225. * The result is <code>true</code> if and only if the argument is
  226. * not <code>null</code> and it represents the same address as
  227. * this object.
  228. * <p>
  229. * Two instances of <code>InetSocketAddress</code> represent the same
  230. * address if both the InetAddresses (or hostnames if it is unresolved) and port
  231. * numbers are equal.
  232. * If both addresses are unresolved, then the hostname & the port number
  233. * are compared.
  234. *
  235. * @param obj the object to compare against.
  236. * @return <code>true</code> if the objects are the same;
  237. * <code>false</code> otherwise.
  238. * @see java.net.InetAddress#equals(java.lang.Object)
  239. */
  240. public final boolean equals(Object obj) {
  241. if (obj == null || !(obj instanceof InetSocketAddress))
  242. return false;
  243. InetSocketAddress sockAddr = (InetSocketAddress) obj;
  244. boolean sameIP = false;
  245. if (this.addr != null)
  246. sameIP = this.addr.equals(sockAddr.addr);
  247. else if (this.hostname != null)
  248. sameIP = (sockAddr.addr == null) &&
  249. this.hostname.equals(sockAddr.hostname);
  250. else
  251. sameIP = (sockAddr.addr == null) && (sockAddr.hostname == null);
  252. return sameIP && (this.port == sockAddr.port);
  253. }
  254. /**
  255. * Returns a hashcode for this socket address.
  256. *
  257. * @return a hash code value for this socket address.
  258. */
  259. public final int hashCode() {
  260. if (addr != null)
  261. return addr.hashCode() + port;
  262. if (hostname != null)
  263. return hostname.hashCode() + port;
  264. return port;
  265. }
  266. }