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      * Returns this socket address' port.
    135      */
    136     public final int getPort() {
    137         return port;
    138     }
    139 
    140     /**
    141      * Returns this socket address' address.
    142      */
    143     public final InetAddress getAddress() {
    144         return addr;
    145     }
    146 
    147     /**
    148      * Returns the hostname, doing a reverse DNS lookup on the {@code InetAddress} if no
    149      * hostname string was provided at construction time. Use {@link #getHostString} to
    150      * avoid the reverse DNS lookup.
    151      */
    152     public final String getHostName() {
    153         return (addr != null) ? addr.getHostName() : hostname;
    154     }
    155 
    156     /**
    157      * Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}.
    158      * Unlike {@link #getHostName}, this method will never cause a DNS lookup.
    159      * @since 1.7
    160      */
    161     public final String getHostString() {
    162         return (hostname != null) ? hostname : addr.getHostAddress();
    163     }
    164 
    165     /**
    166      * Returns whether this socket address is unresolved or not.
    167      *
    168      * @return {@code true} if this socket address is unresolved, {@code false}
    169      *         otherwise.
    170      */
    171     public final boolean isUnresolved() {
    172         return addr == null;
    173     }
    174 
    175     /**
    176      * Returns a string containing the address (or the hostname for an
    177      * unresolved {@code InetSocketAddress}) and port number.
    178      * For example: {@code "www.google.com/74.125.224.115:80"} or {@code "/127.0.0.1:80"}.
    179      */
    180     @Override public String toString() {
    181         return ((addr != null) ? addr.toString() : hostname) + ":" + port;
    182     }
    183 
    184     /**
    185      * Compares two socket endpoints and returns true if they are equal. Two
    186      * socket endpoints are equal if the IP address or the hostname of both are
    187      * equal and they are bound to the same port.
    188      *
    189      * @param socketAddr
    190      *            the object to be tested for equality.
    191      * @return {@code true} if this socket and the given socket object {@code
    192      *         socketAddr} are equal, {@code false} otherwise.
    193      */
    194     @Override
    195     public final boolean equals(Object socketAddr) {
    196         if (this == socketAddr) {
    197             return true;
    198         }
    199         if (!(socketAddr instanceof InetSocketAddress)) {
    200             return false;
    201         }
    202         InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr;
    203 
    204         // check the ports as we always need to do this
    205         if (port != iSockAddr.port) {
    206             return false;
    207         }
    208 
    209         // we only use the hostnames in the comparison if the addrs were not
    210         // resolved
    211         if ((addr == null) && (iSockAddr.addr == null)) {
    212             return hostname.equals(iSockAddr.hostname);
    213         }
    214 
    215         // addrs were resolved so use them for the comparison
    216         if (addr == null) {
    217             // if we are here we know iSockAddr is not null so just return
    218             // false
    219             return false;
    220         }
    221         return addr.equals(iSockAddr.addr);
    222     }
    223 
    224     @Override
    225     public final int hashCode() {
    226         if (addr == null) {
    227             return hostname.hashCode() + port;
    228         }
    229         return addr.hashCode() + port;
    230     }
    231 
    232     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    233         stream.defaultReadObject();
    234     }
    235 }
    236