FileDocCategorySizeDatePackage
MulticastSocket.javaAPI DocAndroid 1.5 API23833Wed May 06 22:41:04 BST 2009java.net

MulticastSocket

public class MulticastSocket extends DatagramSocket
This class implements a multicast socket for sending and receiving IP multicast datagram packets.
see
DatagramSocket
since
Android 1.0

Fields Summary
static final int
SO_REUSEPORT
private InetAddress
interfaceSet
Constructors Summary
public MulticastSocket()
Constructs a multicast socket, bound to any available port on the localhost.

throws
IOException if an error occurs creating or binding the socket.
since
Android 1.0


                                                
        
        super();
        setReuseAddress(true);
    
public MulticastSocket(SocketAddress localAddr)
Constructs a {@code MulticastSocket} bound to the host/port specified by the {@code SocketAddress}, or an unbound {@code DatagramSocket} if the {@code SocketAddress} is {@code null}.

param
localAddr the local machine address and port to bind to.
throws
IllegalArgumentException if the {@code SocketAddress} is not supported.
throws
IOException if an error occurs creating or binding the socket.
since
Android 1.0

        super(localAddr);
        setReuseAddress(true);
    
public MulticastSocket(int aPort)
Constructs a multicast socket, bound to the specified port on the localhost.

param
aPort the port to bind on the localhost.
throws
IOException if an error occurs creating or binding the socket.
since
Android 1.0

        super(aPort);
        setReuseAddress(true);
    
Methods Summary
synchronized voidcreateSocket(int aPort, java.net.InetAddress addr)

        impl = factory != null ? factory.createDatagramSocketImpl()
                : SocketImplProvider.getMulticastSocketImpl();
        impl.create();
        try {
            // the required default options are now set in the VM where they
            // should be
            impl.bind(aPort, addr);
            isBound = true;
        } catch (SocketException e) {
            close();
            throw e;
        }
    
public java.net.InetAddressgetInterface()
Gets the network address used by this socket. This is useful on multihomed machines.

return
the address of the network interface through which the datagram packets are sent or received.
exception
SocketException if an error occurs while getting the interface address.
since
Android 1.0

        checkClosedAndBind(false);
        if (interfaceSet == null) {
            InetAddress ipvXaddress = (InetAddress) impl
                    .getOption(SocketOptions.IP_MULTICAST_IF);
            if (ipvXaddress.isAnyLocalAddress()) {
                // the address was not set at the IPV4 level so check the IPV6
                // level
                NetworkInterface theInterface = getNetworkInterface();
                if (theInterface != null) {
                    Enumeration<InetAddress> addresses = theInterface
                            .getInetAddresses();
                    if (addresses != null) {
                        while (addresses.hasMoreElements()) {
                            InetAddress nextAddress = addresses.nextElement();
                            if (nextAddress instanceof Inet6Address) {
                                return nextAddress;
                            }
                        }
                    }
                }
            }
            return ipvXaddress;
        }
        return interfaceSet;
    
public booleangetLoopbackMode()
Gets the state of the {@code SocketOptions.IP_MULTICAST_LOOP}.

return
{@code true} if the IP multicast loop is enabled, {@code false} otherwise.
throws
SocketException if the socket is closed or the option is invalid.
since
Android 1.0

        checkClosedAndBind(false);
        return !((Boolean) impl.getOption(SocketOptions.IP_MULTICAST_LOOP))
                .booleanValue();
    
public java.net.NetworkInterfacegetNetworkInterface()
Gets the network interface used by this socket. This is useful on multihomed machines.

return
the network interface used by this socket or {@code null} if no interface is set.
exception
SocketException if an error occurs while getting the interface.
since
Android 1.0

        checkClosedAndBind(false);

        // check if it is set at the IPV6 level. If so then use that. Otherwise
        // do it at the IPV4 level
        Integer theIndex = Integer.valueOf(0);
        try {
            theIndex = (Integer) impl.getOption(SocketOptions.IP_MULTICAST_IF2);
        } catch (SocketException e) {
            // we may get an exception if IPV6 is not enabled.
        }

        if (theIndex.intValue() != 0) {
            Enumeration<NetworkInterface> theInterfaces = NetworkInterface
                    .getNetworkInterfaces();
            while (theInterfaces.hasMoreElements()) {
                NetworkInterface nextInterface = theInterfaces.nextElement();
                if (nextInterface.getIndex() == theIndex.intValue()) {
                    return nextInterface;
                }
            }
        }

        // ok it was not set at the IPV6 level so try at the IPV4 level
        InetAddress theAddress = (InetAddress) impl
                .getOption(SocketOptions.IP_MULTICAST_IF);
        if (theAddress != null) {
            if (!theAddress.isAnyLocalAddress()) {
                return NetworkInterface.getByInetAddress(theAddress);
            }

            // not set as we got the any address so return a dummy network
            // interface with only the any address. We do this to be
            // compatible
            InetAddress theAddresses[] = new InetAddress[1];
            if ((Socket.preferIPv4Stack() == false)
                    && (InetAddress.preferIPv6Addresses() == true)) {
                theAddresses[0] = Inet6Address.ANY;
            } else {
                theAddresses[0] = InetAddress.ANY;
            }
            return new NetworkInterface(null, null, theAddresses,
                    NetworkInterface.UNSET_INTERFACE_INDEX);
        }

        // ok not set at all so return null
        return null;
    
public bytegetTTL()
Gets the time-to-live (TTL) for multicast packets sent on this socket.

return
the default value for the time-to-life field.
exception
IOException if an error occurs reading the default value.
deprecated
Replaced by {@link #getTimeToLive}
see
#getTimeToLive()
since
Android 1.0

        checkClosedAndBind(false);
        return impl.getTTL();
    
public intgetTimeToLive()
Gets the time-to-live (TTL) for multicast packets sent on this socket.

return
the default value for the time-to-life field.
exception
IOException if an error occurs reading the default value.
since
Android 1.0

        checkClosedAndBind(false);
        return impl.getTimeToLive();
    
booleanisMulticastSocket()

        return true;
    
public voidjoinGroup(java.net.InetAddress groupAddr)
Adds this socket to the specified multicast group. A socket must join a group before data may be received. A socket may be a member of multiple groups but may join any group only once.

param
groupAddr the multicast group to be joined.
exception
IOException if an error occurs while joining a group.
since
Android 1.0

        checkClosedAndBind(false);
        if (!groupAddr.isMulticastAddress()) {
            throw new IOException(Msg.getString("K0039")); //$NON-NLS-1$
        }
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkMulticast(groupAddr);
        }
        impl.join(groupAddr);
    
public voidjoinGroup(java.net.SocketAddress groupAddress, java.net.NetworkInterface netInterface)
Adds this socket to the specified multicast group. A socket must join a group before data may be received. A socket may be a member of multiple groups but may join any group only once.

param
groupAddress the multicast group to be joined.
param
netInterface the network interface on which the datagram packets will be received.
exception
IOException if the specified address is not a multicast address.
exception
SecurityException if the caller is not authorized to join the group.
exception
IllegalArgumentException if no multicast group is specified.
since
Android 1.0

        checkClosedAndBind(false);
        if (null == groupAddress) {
            throw new IllegalArgumentException(Msg.getString("K0318")); //$NON-NLS-1$
        }

        if ((netInterface != null) && (netInterface.getFirstAddress() == null)) {
            // this is ok if we could set it at the
            throw new SocketException(Msg.getString("K0335")); //$NON-NLS-1$
        }

        if (!(groupAddress instanceof InetSocketAddress)) {
            throw new IllegalArgumentException(Msg.getString(
                    "K0316", groupAddress.getClass())); //$NON-NLS-1$
        }

        InetAddress groupAddr = ((InetSocketAddress) groupAddress).getAddress();

        if (groupAddr == null) {
            throw new SocketException(Msg.getString("K0331")); //$NON-NLS-1$
        }

        if (!groupAddr.isMulticastAddress()) {
            throw new IOException(Msg.getString("K0039")); //$NON-NLS-1$
        }

        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkMulticast(groupAddr);
        }
        impl.joinGroup(groupAddress, netInterface);
    
public voidleaveGroup(java.net.InetAddress groupAddr)
Removes this socket from the specified multicast group.

param
groupAddr the multicast group to be left.
exception
IOException if the specified group address is not a multicast address.
exception
SecurityException if the caller is not authorized to leave the group.
since
Android 1.0

        checkClosedAndBind(false);
        if (!groupAddr.isMulticastAddress()) {
            throw new IOException(Msg.getString("K003a")); //$NON-NLS-1$
        }
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkMulticast(groupAddr);
        }
        impl.leave(groupAddr);
    
public voidleaveGroup(java.net.SocketAddress groupAddress, java.net.NetworkInterface netInterface)
Removes this socket from the specified multicast group.

param
groupAddress the multicast group to be left.
param
netInterface the network interface on which the addresses should be dropped.
exception
IOException if the specified group address is not a multicast address.
exception
SecurityException if the caller is not authorized to leave the group.
exception
IllegalArgumentException if no multicast group is specified.
since
Android 1.0

        checkClosedAndBind(false);
        if (null == groupAddress) {
            throw new IllegalArgumentException(Msg.getString("K0318")); //$NON-NLS-1$
        }

        if ((netInterface != null) && (netInterface.getFirstAddress() == null)) {
            // this is ok if we could set it at the
            throw new SocketException(Msg.getString("K0335")); //$NON-NLS-1$
        }

        if (!(groupAddress instanceof InetSocketAddress)) {
            throw new IllegalArgumentException(Msg.getString(
                    "K0316", groupAddress.getClass())); //$NON-NLS-1$
        }

        InetAddress groupAddr = ((InetSocketAddress) groupAddress).getAddress();

        if (groupAddr == null) {
            throw new SocketException(Msg.getString("K0331")); //$NON-NLS-1$
        }

        if (!groupAddr.isMulticastAddress()) {
            throw new IOException(Msg.getString("K003a")); //$NON-NLS-1$
        }
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkMulticast(groupAddr);
        }
        impl.leaveGroup(groupAddress, netInterface);
    
public voidsend(java.net.DatagramPacket pack, byte ttl)
Send the packet on this socket. The packet must satisfy the security policy before it may be sent.

param
pack the {@code DatagramPacket} to send
param
ttl the TTL setting for this transmission, overriding the socket default
exception
IOException if an error occurs while sending data or setting options.
deprecated
use {@link #setTimeToLive}.
since
Android 1.0

        checkClosedAndBind(false);
        InetAddress packAddr = pack.getAddress();
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            if (packAddr.isMulticastAddress()) {
                security.checkMulticast(packAddr, ttl);
            } else {
                security.checkConnect(packAddr.getHostName(), pack.getPort());
            }
        }
        int currTTL = getTimeToLive();
        if (packAddr.isMulticastAddress() && (byte) currTTL != ttl) {
            try {
                setTimeToLive(ttl & 0xff);
                impl.send(pack);
            } finally {
                setTimeToLive(currTTL);
            }
        } else {
            impl.send(pack);
        }
    
public voidsetInterface(java.net.InetAddress addr)
Sets the interface address used by this socket. This allows to send multicast packets on a different interface than the default interface of the local system. This is useful on multihomed machines.

param
addr the multicast interface network address to set.
exception
SocketException if an error occurs while setting the network interface address option.
since
Android 1.0

        checkClosedAndBind(false);
        if (addr == null) {
            throw new NullPointerException();
        }
        if (addr.isAnyLocalAddress()) {
            impl.setOption(SocketOptions.IP_MULTICAST_IF, InetAddress.ANY);
        } else if (addr instanceof Inet4Address) {
            impl.setOption(SocketOptions.IP_MULTICAST_IF, addr);
            // keep the address used to do the set as we must return the same
            // value and for IPv6 we may not be able to get it back uniquely
            interfaceSet = addr;
        }

        /*
         * now we should also make sure this works for IPV6 get the network
         * interface for the address and set the interface using its index
         * however if IPV6 is not enabled then we may get an exception. if IPV6
         * is not enabled
         */
        NetworkInterface theInterface = NetworkInterface.getByInetAddress(addr);
        if ((theInterface != null) && (theInterface.getIndex() != 0)) {
            try {
                impl.setOption(SocketOptions.IP_MULTICAST_IF2, Integer
                        .valueOf(theInterface.getIndex()));
            } catch (SocketException e) {
                // Ignored
            }
        } else if (addr.isAnyLocalAddress()) {
            try {
                impl.setOption(SocketOptions.IP_MULTICAST_IF2, Integer
                        .valueOf(0));
            } catch (SocketException e) {
                // Ignored
            }
        } else if (addr instanceof Inet6Address) {
            throw new SocketException(Msg.getString("K0338")); //$NON-NLS-1$
        }
    
public voidsetLoopbackMode(boolean loop)
Sets the {@code SocketOptions.IP_MULTICAST_LOOP}.

param
loop the value for the socket option socket {@code SocketOptions.IP_MULTICAST_LOOP}.
throws
SocketException if the socket is closed or the option is invalid.
since
Android 1.0

        checkClosedAndBind(false);
        impl.setOption(SocketOptions.IP_MULTICAST_LOOP, loop ? Boolean.FALSE
                : Boolean.TRUE);
    
public voidsetNetworkInterface(java.net.NetworkInterface netInterface)
Sets the network interface used by this socket. This is useful for multihomed machines.

param
netInterface the multicast network interface to set.
exception
SocketException if an error occurs while setting the network interface option.
since
Android 1.0


        checkClosedAndBind(false);

        if (netInterface == null) {
            // throw a socket exception indicating that we do not support this
            throw new SocketException(Msg.getString("K0334")); //$NON-NLS-1$
        }

        InetAddress firstAddress = netInterface.getFirstAddress();
        if (firstAddress == null) {
            // this is ok if we could set it at the
            throw new SocketException(Msg.getString("K0335")); //$NON-NLS-1$
        }

        if (netInterface.getIndex() == NetworkInterface.UNSET_INTERFACE_INDEX) {
            // set the address using IP_MULTICAST_IF to make sure this
            // works for both IPV4 and IPV6
            impl.setOption(SocketOptions.IP_MULTICAST_IF, InetAddress.ANY);

            try {
                // we have the index so now we pass set the interface
                // using IP_MULTICAST_IF2. This is what is used to set
                // the interface on systems which support IPV6
                impl.setOption(SocketOptions.IP_MULTICAST_IF2, Integer
                        .valueOf(NetworkInterface.NO_INTERFACE_INDEX));
            } catch (SocketException e) {
                // for now just do this, -- could be narrowed?
            }
        }

        /*
         * Now try to set using IPV4 way. However, if interface passed in has no
         * IP addresses associated with it then we cannot do it. first we have
         * to make sure there is an IPV4 address that we can use to call set
         * interface otherwise we will not set it
         */
        Enumeration<InetAddress> theAddresses = netInterface.getInetAddresses();
        boolean found = false;
        firstAddress = null;
        while ((theAddresses.hasMoreElements()) && (found != true)) {
            InetAddress theAddress = theAddresses.nextElement();
            if (theAddress instanceof Inet4Address) {
                firstAddress = theAddress;
                found = true;
            }
        }
        if (netInterface.getIndex() == NetworkInterface.NO_INTERFACE_INDEX) {
            // the system does not support IPV6 and does not provide
            // indexes for the network interfaces. Just pass in the
            // first address for the network interface
            if (firstAddress != null) {
                impl.setOption(SocketOptions.IP_MULTICAST_IF, firstAddress);
            } else {
                /*
                 * we should never get here as there should not be any network
                 * interfaces which have no IPV4 address and which does not have
                 * the network interface index not set correctly
                 */
                throw new SocketException(Msg.getString("K0335")); //$NON-NLS-1$
            }
        } else {
            // set the address using IP_MULTICAST_IF to make sure this
            // works for both IPV4 and IPV6
            if (firstAddress != null) {
                impl.setOption(SocketOptions.IP_MULTICAST_IF, firstAddress);
            }

            try {
                // we have the index so now we pass set the interface
                // using IP_MULTICAST_IF2. This is what is used to set
                // the interface on systems which support IPV6
                impl.setOption(SocketOptions.IP_MULTICAST_IF2, Integer
                        .valueOf(netInterface.getIndex()));
            } catch (SocketException e) {
                // for now just do this -- could be narrowed?
            }
        }

        interfaceSet = null;
    
public voidsetTTL(byte ttl)
Sets the time-to-live (TTL) for multicast packets sent on this socket. Valid TTL values are between 0 and 255 inclusive.

param
ttl the default time-to-live field value for packets sent on this socket: {@code 0 <= ttl <= 255}.
exception
IOException if an error occurs while setting the TTL option value.
deprecated
Replaced by {@link #setTimeToLive}
see
#setTimeToLive(int)
since
Android 1.0

        checkClosedAndBind(false);
        impl.setTTL(ttl);
    
public voidsetTimeToLive(int ttl)
Sets the time-to-live (TTL) for multicast packets sent on this socket. Valid TTL values are between 0 and 255 inclusive.

param
ttl the default time-to-live field value for packets sent on this socket. {@code 0 <= ttl <= 255}.
exception
IOException if an error occurs while setting the TTL option value.
since
Android 1.0

        checkClosedAndBind(false);
        if (ttl < 0 || ttl > 255) {
            throw new IllegalArgumentException(Msg.getString("K003c")); //$NON-NLS-1$
        }
        impl.setTimeToLive(ttl);