InetSocketAddress.java revision 4f9ffffd8a2835c30647f9785afb48fa96a0f045
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
18package java.net;
19
20import java.io.IOException;
21import 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 */
27public 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     * Creates a socket endpoint with the given port number {@code port} and
38     * no specified address. The range for valid port numbers is between 0 and
39     * 65535 inclusive.
40     *
41     * @param port
42     *            the specified port number to which this socket is bound.
43     */
44    public InetSocketAddress(int port) {
45        this((InetAddress) null, port);
46    }
47
48    /**
49     * Creates a socket endpoint with the given port number {@code port} and
50     * {@code address}. The range for valid port numbers is between 0 and 65535
51     * inclusive. If {@code address} is {@code null} this socket is bound to the
52     * IPv4 wildcard address.
53     *
54     * @param port
55     *            the specified port number to which this socket is bound.
56     * @param address
57     *            the specified address to which this socket is bound.
58     */
59    public InetSocketAddress(InetAddress address, int port) {
60        if (port < 0 || port > 65535) {
61            throw new IllegalArgumentException("port=" + port);
62        }
63        this.addr = (address == null) ? Inet4Address.ANY : address;
64        this.hostname = null;
65        this.port = port;
66    }
67
68    /**
69     * Creates a socket endpoint with the given port number {@code port} and the
70     * hostname {@code host}. The hostname is tried to be resolved and cannot be
71     * {@code null}. The range for valid port numbers is between 0 and 65535
72     * inclusive.
73     *
74     * @param port
75     *            the specified port number to which this socket is bound.
76     * @param host
77     *            the specified hostname to which this socket is bound.
78     */
79    public InetSocketAddress(String host, int port) {
80        this(host, port, true);
81    }
82
83    /*
84     * Internal constructor for InetSocketAddress(String, int) and
85     * createUnresolved(String, int);
86     */
87    InetSocketAddress(String hostname, int port, boolean needResolved) {
88        if (hostname == null || port < 0 || port > 65535) {
89            throw new IllegalArgumentException("host=" + hostname + ", port=" + port);
90        }
91
92        InetAddress addr = null;
93        if (needResolved) {
94            try {
95                addr = InetAddress.getByName(hostname);
96                hostname = null;
97            } catch (UnknownHostException ignored) {
98            }
99        }
100        this.addr = addr;
101        this.hostname = hostname;
102        this.port = port;
103    }
104
105    /**
106     * Creates an {@code InetSocketAddress} without trying to resolve the
107     * hostname into an {@code InetAddress}. The address field is marked as
108     * unresolved.
109     *
110     * @param host
111     *            the specified hostname to which this socket is bound.
112     * @param port
113     *            the specified port number to which this socket is bound.
114     * @return the created InetSocketAddress instance.
115     * @throws IllegalArgumentException
116     *             if the hostname {@code host} is {@code null} or the port is
117     *             not in the range between 0 and 65535.
118     */
119    public static InetSocketAddress createUnresolved(String host, int port) {
120        return new InetSocketAddress(host, port, false);
121    }
122
123    /**
124     * Gets the port number of this socket.
125     *
126     * @return the socket endpoint port number.
127     */
128    public final int getPort() {
129        return port;
130    }
131
132    /**
133     * Gets the address of this socket.
134     *
135     * @return the socket endpoint address.
136     */
137    public final InetAddress getAddress() {
138        return addr;
139    }
140
141    /**
142     * Returns the hostname, doing a reverse lookup on the {@code InetAddress} if no
143     * hostname string was provided at construction time.
144     */
145    public final String getHostName() {
146        return (addr != null) ? addr.getHostName() : hostname;
147    }
148
149    /**
150     * Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}.
151     * Unlike {@link #getHostName}, this method will never cause a DNS lookup.
152     * @since 1.7
153     * @hide 1.7 - remember to add a link in the getHostName documentation!
154     */
155    public final String getHostString() {
156        return (hostname != null) ? hostname : addr.getHostAddress();
157    }
158
159    /**
160     * Returns whether this socket address is unresolved or not.
161     *
162     * @return {@code true} if this socket address is unresolved, {@code false}
163     *         otherwise.
164     */
165    public final boolean isUnresolved() {
166        return addr == null;
167    }
168
169    /**
170     * Gets a string representation of this socket included the address and the
171     * port number.
172     *
173     * @return the address and port number as a textual representation.
174     */
175    @Override
176    public String toString() {
177        return ((addr != null) ? addr.toString() : hostname) + ":" + port;
178    }
179
180    /**
181     * Compares two socket endpoints and returns true if they are equal. Two
182     * socket endpoints are equal if the IP address or the hostname of both are
183     * equal and they are bound to the same port.
184     *
185     * @param socketAddr
186     *            the object to be tested for equality.
187     * @return {@code true} if this socket and the given socket object {@code
188     *         socketAddr} are equal, {@code false} otherwise.
189     */
190    @Override
191    public final boolean equals(Object socketAddr) {
192        if (this == socketAddr) {
193            return true;
194        }
195        if (!(socketAddr instanceof InetSocketAddress)) {
196            return false;
197        }
198        InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr;
199
200        // check the ports as we always need to do this
201        if (port != iSockAddr.port) {
202            return false;
203        }
204
205        // we only use the hostnames in the comparison if the addrs were not
206        // resolved
207        if ((addr == null) && (iSockAddr.addr == null)) {
208            return hostname.equals(iSockAddr.hostname);
209        }
210
211        // addrs were resolved so use them for the comparison
212        if (addr == null) {
213            // if we are here we know iSockAddr is not null so just return
214            // false
215            return false;
216        }
217        return addr.equals(iSockAddr.addr);
218    }
219
220    @Override
221    public final int hashCode() {
222        if (addr == null) {
223            return hostname.hashCode() + port;
224        }
225        return addr.hashCode() + port;
226    }
227
228    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
229        stream.defaultReadObject();
230    }
231}
232