Home | History | Annotate | Download | only in net
      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