blob: 49dcfc493d30969835015f71f5effa6b48a4e11e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.net;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* This class represents a socket endpoint described by a IP address and a port
* number. It is a concrete implementation of {@code SocketAddress} for IP.
*/
public class InetSocketAddress extends SocketAddress {
private static final long serialVersionUID = 5076001401234631237L;
// Exactly one of hostname or addr should be set.
private final InetAddress addr;
private final String hostname;
private final int port;
/**
* @hide internal use only
*/
public InetSocketAddress() {
// These will be filled in the native implementation of recvfrom.
this.addr = null;
this.hostname = null;
this.port = -1;
}
/**
* Creates a socket endpoint with the given port number {@code port} and
* no specified address. The range for valid port numbers is between 0 and
* 65535 inclusive.
*
* @param port
* the specified port number to which this socket is bound.
*/
public InetSocketAddress(int port) {
this((InetAddress) null, port);
}
/**
* Creates a socket endpoint with the given port number {@code port} and
* {@code address}. The range for valid port numbers is between 0 and 65535
* inclusive. If {@code address} is {@code null} this socket is bound to the
* IPv4 wildcard address.
*
* @param port
* the specified port number to which this socket is bound.
* @param address
* the specified address to which this socket is bound.
*/
public InetSocketAddress(InetAddress address, int port) {
if (port < 0 || port > 65535) {
throw new IllegalArgumentException("port=" + port);
}
this.addr = (address == null) ? Inet4Address.ANY : address;
this.hostname = null;
this.port = port;
}
/**
* Creates a socket endpoint with the given port number {@code port} and the
* hostname {@code host}. The hostname is tried to be resolved and cannot be
* {@code null}. The range for valid port numbers is between 0 and 65535
* inclusive.
*
* @param port
* the specified port number to which this socket is bound.
* @param host
* the specified hostname to which this socket is bound.
*/
public InetSocketAddress(String host, int port) {
this(host, port, true);
}
/*
* Internal constructor for InetSocketAddress(String, int) and
* createUnresolved(String, int);
*/
InetSocketAddress(String hostname, int port, boolean needResolved) {
if (hostname == null || port < 0 || port > 65535) {
throw new IllegalArgumentException("host=" + hostname + ", port=" + port);
}
InetAddress addr = null;
if (needResolved) {
try {
addr = InetAddress.getByName(hostname);
hostname = null;
} catch (UnknownHostException ignored) {
}
}
this.addr = addr;
this.hostname = hostname;
this.port = port;
}
/**
* Creates an {@code InetSocketAddress} without trying to resolve the
* hostname into an {@code InetAddress}. The address field is marked as
* unresolved.
*
* @param host
* the specified hostname to which this socket is bound.
* @param port
* the specified port number to which this socket is bound.
* @return the created InetSocketAddress instance.
* @throws IllegalArgumentException
* if the hostname {@code host} is {@code null} or the port is
* not in the range between 0 and 65535.
*/
public static InetSocketAddress createUnresolved(String host, int port) {
return new InetSocketAddress(host, port, false);
}
/**
* Gets the port number of this socket.
*
* @return the socket endpoint port number.
*/
public final int getPort() {
return port;
}
/**
* Gets the address of this socket.
*
* @return the socket endpoint address.
*/
public final InetAddress getAddress() {
return addr;
}
/**
* Returns the hostname, doing a reverse lookup on the {@code InetAddress} if no
* hostname string was provided at construction time.
*/
public final String getHostName() {
return (addr != null) ? addr.getHostName() : hostname;
}
/**
* Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}.
* Unlike {@link #getHostName}, this method will never cause a DNS lookup.
* @since 1.7
* @hide 1.7 - remember to add a link in the getHostName documentation!
*/
public final String getHostString() {
return (hostname != null) ? hostname : addr.getHostAddress();
}
/**
* Returns whether this socket address is unresolved or not.
*
* @return {@code true} if this socket address is unresolved, {@code false}
* otherwise.
*/
public final boolean isUnresolved() {
return addr == null;
}
/**
* Returns a string containing the address (or the hostname for an
* unresolved {@code InetSocketAddress}) and port number.
* For example: {@code "www.google.com/74.125.224.115:80"} or {@code "/127.0.0.1:80"}.
*/
@Override public String toString() {
return ((addr != null) ? addr.toString() : hostname) + ":" + port;
}
/**
* Compares two socket endpoints and returns true if they are equal. Two
* socket endpoints are equal if the IP address or the hostname of both are
* equal and they are bound to the same port.
*
* @param socketAddr
* the object to be tested for equality.
* @return {@code true} if this socket and the given socket object {@code
* socketAddr} are equal, {@code false} otherwise.
*/
@Override
public final boolean equals(Object socketAddr) {
if (this == socketAddr) {
return true;
}
if (!(socketAddr instanceof InetSocketAddress)) {
return false;
}
InetSocketAddress iSockAddr = (InetSocketAddress) socketAddr;
// check the ports as we always need to do this
if (port != iSockAddr.port) {
return false;
}
// we only use the hostnames in the comparison if the addrs were not
// resolved
if ((addr == null) && (iSockAddr.addr == null)) {
return hostname.equals(iSockAddr.hostname);
}
// addrs were resolved so use them for the comparison
if (addr == null) {
// if we are here we know iSockAddr is not null so just return
// false
return false;
}
return addr.equals(iSockAddr.addr);
}
@Override
public final int hashCode() {
if (addr == null) {
return hostname.hashCode() + port;
}
return addr.hashCode() + port;
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
}
}