InetSocketAddress.java revision c0372d90016d241ac979faa6fa1731f30b6f2a03
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    private String hostname;
32
33    private InetAddress addr;
34
35    private int port;
36
37    /**
38     * Creates a socket endpoint with the given port number {@code port} and
39     * no specified address. The range for valid port numbers is between 0 and
40     * 65535 inclusive.
41     *
42     * @param port
43     *            the specified port number to which this socket is bound.
44     */
45    public InetSocketAddress(int port) {
46        this((InetAddress) null, port);
47    }
48
49    /**
50     * Creates a socket endpoint with the given port number {@code port} and
51     * {@code address}. The range for valid port numbers is between 0 and 65535
52     * inclusive. If {@code address} is {@code null} this socket is bound to the
53     * IPv4 wildcard address.
54     *
55     * @param port
56     *            the specified port number to which this socket is bound.
57     * @param address
58     *            the specified address to which this socket is bound.
59     */
60    public InetSocketAddress(InetAddress address, int port) {
61        if (port < 0 || port > 65535) {
62            throw new IllegalArgumentException();
63        }
64        if (address == null) {
65            addr = Inet4Address.ANY;
66        } else {
67            addr = address;
68        }
69        hostname = addr.getHostName();
70        this.port = port;
71    }
72
73    /**
74     * Creates a socket endpoint with the given port number {@code port} and the
75     * hostname {@code host}. The hostname is tried to be resolved and cannot be
76     * {@code null}. The range for valid port numbers is between 0 and 65535
77     * inclusive.
78     *
79     * @param port
80     *            the specified port number to which this socket is bound.
81     * @param host
82     *            the specified hostname to which this socket is bound.
83     * @throws SecurityException
84     *             if a {@link SecurityManager} is installed and its {@code
85     *             checkConnect()} method does not allow the resolving of the
86     *             host name.
87     */
88    public InetSocketAddress(String host, int port) {
89        this(host, port, true);
90    }
91
92    /*
93     * Internal constructor for InetSocketAddress(String, int) and
94     * createUnresolved(String, int);
95     */
96    InetSocketAddress(String hostname, int port, boolean needResolved) {
97        if (hostname == null || port < 0 || port > 65535) {
98            throw new IllegalArgumentException("host=" + hostname + ", port=" + port);
99        }
100        this.hostname = hostname;
101        this.port = port;
102
103        if (needResolved) {
104            SecurityManager smgr = System.getSecurityManager();
105            if (smgr != null) {
106                smgr.checkConnect(hostname, port);
107            }
108            try {
109                this.addr = InetAddress.getByName(hostname);
110                this.hostname = null;
111            } catch (UnknownHostException ignored) {
112            }
113        }
114    }
115
116    /**
117     * Creates an {@code InetSocketAddress} without trying to resolve the
118     * hostname into an {@code InetAddress}. The address field is marked as
119     * unresolved.
120     *
121     * @param host
122     *            the specified hostname to which this socket is bound.
123     * @param port
124     *            the specified port number to which this socket is bound.
125     * @return the created InetSocketAddress instance.
126     * @throws IllegalArgumentException
127     *             if the hostname {@code host} is {@code null} or the port is
128     *             not in the range between 0 and 65535.
129     */
130    public static InetSocketAddress createUnresolved(String host, int port) {
131        return new InetSocketAddress(host, port, false);
132    }
133
134    /**
135     * Gets the port number of this socket.
136     *
137     * @return the socket endpoint port number.
138     */
139    public final int getPort() {
140        return port;
141    }
142
143    /**
144     * Gets the address of this socket.
145     *
146     * @return the socket endpoint address.
147     */
148    public final InetAddress getAddress() {
149        return addr;
150    }
151
152    /**
153     * Gets the hostname of this socket.
154     *
155     * @return the socket endpoint hostname.
156     */
157    public final String getHostName() {
158        return (null != addr) ? addr.getHostName() : hostname;
159    }
160
161    /**
162     * Returns whether this socket address is unresolved or not.
163     *
164     * @return {@code true} if this socket address is unresolved, {@code false}
165     *         otherwise.
166     */
167    public final boolean isUnresolved() {
168        return addr == null;
169    }
170
171    /**
172     * Gets a string representation of this socket included the address and the
173     * port number.
174     *
175     * @return the address and port number as a textual representation.
176     */
177    @Override
178    public String toString() {
179        String host;
180        if (addr != null) {
181            host = addr.toString();
182        } else {
183            host = hostname;
184        }
185        return host + ":" + 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    /**
229     * Gets the hashcode of this socket.
230     *
231     * @return the appropriate hashcode.
232     */
233    @Override
234    public final int hashCode() {
235        if (addr == null) {
236            return hostname.hashCode() + port;
237        }
238        return addr.hashCode() + port;
239    }
240
241    private void readObject(ObjectInputStream stream) throws IOException,
242            ClassNotFoundException {
243        stream.defaultReadObject();
244    }
245}
246