1 /* 2 * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.net; 27 28 import java.io.IOException; 29 import java.util.Collections; 30 import java.util.Enumeration; 31 import java.util.Set; 32 /** 33 * The multicast datagram socket class is useful for sending 34 * and receiving IP multicast packets. A MulticastSocket is 35 * a (UDP) DatagramSocket, with additional capabilities for 36 * joining "groups" of other multicast hosts on the internet. 37 * <P> 38 * A multicast group is specified by a class D IP address 39 * and by a standard UDP port number. Class D IP addresses 40 * are in the range {@code 224.0.0.0} to {@code 239.255.255.255}, 41 * inclusive. The address 224.0.0.0 is reserved and should not be used. 42 * <P> 43 * One would join a multicast group by first creating a MulticastSocket 44 * with the desired port, then invoking the 45 * <CODE>joinGroup(InetAddress groupAddr)</CODE> 46 * method: 47 * <PRE> 48 * // join a Multicast group and send the group salutations 49 * ... 50 * String msg = "Hello"; 51 * InetAddress mcastaddr = InetAddress.getByName("228.5.6.7"); 52 * InetSocketAddress group = new InetSocketAddress(mcastaddr, port); 53 * NetworkInterface netIf = NetworkInterface.getByName("bge0"); 54 * MulticastSocket s = new MulticastSocket(6789); 55 * 56 * s.joinGroup(group, netIf); 57 * byte[] msgBytes = msg.getBytes(StandardCharsets.UTF_8); 58 * DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, 59 * group, 6789); 60 * s.send(hi); 61 * // get their responses! 62 * byte[] buf = new byte[1000]; 63 * DatagramPacket recv = new DatagramPacket(buf, buf.length); 64 * s.receive(recv); 65 * ... 66 * // OK, I'm done talking - leave the group... 67 * s.leaveGroup(group, netIf); 68 * </PRE> 69 * 70 * When one sends a message to a multicast group, <B>all</B> subscribing 71 * recipients to that host and port receive the message (within the 72 * time-to-live range of the packet, see below). The socket needn't 73 * be a member of the multicast group to send messages to it. 74 * <P> 75 * When a socket subscribes to a multicast group/port, it receives 76 * datagrams sent by other hosts to the group/port, as do all other 77 * members of the group and port. A socket relinquishes membership 78 * in a group by the leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) 79 * method. 80 * <B>Multiple MulticastSockets</B> may subscribe to a multicast group 81 * and port concurrently, and they will all receive group datagrams. 82 * 83 * <p> The {@code DatagramSocket} and {@code MulticastSocket} 84 * classes define convenience methods to set and get several 85 * socket options. Like {@code DatagramSocket} this class also 86 * supports the {@link #setOption(SocketOption, Object) setOption} 87 * and {@link #getOption(SocketOption) getOption} methods to set 88 * and query socket options. 89 * In addition to the socket options supported by 90 * <a href="DatagramSocket.html#SocketOptions">{@code DatagramSocket}</a>, a 91 * {@code MulticastSocket} supports the following socket options: 92 * <blockquote> 93 * <a id="MulticastOptions"></a> 94 * <table class="striped"> 95 * <caption style="display:none">Socket options</caption> 96 * <thead> 97 * <tr> 98 * <th scope="col">Option Name</th> 99 * <th scope="col">Description</th> 100 * </tr> 101 * </thead> 102 * <tbody> 103 * <tr> 104 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_IF IP_MULTICAST_IF} </th> 105 * <td> The network interface for Internet Protocol (IP) multicast datagrams </td> 106 * </tr> 107 * <tr> 108 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_TTL 109 * IP_MULTICAST_TTL} </th> 110 * <td> The <em>time-to-live</em> for Internet Protocol (IP) multicast 111 * datagrams </td> 112 * </tr> 113 * <tr> 114 * <th scope="row"> {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP 115 * IP_MULTICAST_LOOP} </th> 116 * <td> Loopback for Internet Protocol (IP) multicast datagrams </td> 117 * </tr> 118 * </tbody> 119 * </table> 120 * </blockquote> 121 * Additional (implementation specific) options may also be supported. 122 * 123 * @author Pavani Diwanji 124 * @since 1.1 125 */ 126 public class MulticastSocket extends DatagramSocket { 127 128 /** 129 * Used on some platforms to record if an outgoing interface 130 * has been set for this socket. 131 */ 132 private boolean interfaceSet; 133 134 /** 135 * Create a multicast socket. 136 * 137 * <p> 138 * If there is a security manager, its {@code checkListen} method is first 139 * called with 0 as its argument to ensure the operation is allowed. This 140 * could result in a SecurityException. 141 * <p> 142 * When the socket is created the 143 * {@link DatagramSocket#setReuseAddress(boolean)} method is called to 144 * enable the SO_REUSEADDR socket option. 145 * 146 * @throws IOException if an I/O exception occurs while creating the 147 * MulticastSocket 148 * @throws SecurityException if a security manager exists and its 149 * {@code checkListen} method doesn't allow the operation. 150 * @see SecurityManager#checkListen 151 * @see java.net.DatagramSocket#setReuseAddress(boolean) 152 * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object) 153 */ 154 public MulticastSocket() throws IOException { 155 this(new InetSocketAddress(0)); 156 } 157 158 /** 159 * Create a multicast socket and bind it to a specific port. 160 * 161 * <p>If there is a security manager, 162 * its {@code checkListen} method is first called 163 * with the {@code port} argument 164 * as its argument to ensure the operation is allowed. 165 * This could result in a SecurityException. 166 * <p> 167 * When the socket is created the 168 * {@link DatagramSocket#setReuseAddress(boolean)} method is 169 * called to enable the SO_REUSEADDR socket option. 170 * 171 * @param port port to use 172 * @throws IOException if an I/O exception occurs 173 * while creating the MulticastSocket 174 * @throws SecurityException if a security manager exists and its 175 * {@code checkListen} method doesn't allow the operation. 176 * @see SecurityManager#checkListen 177 * @see java.net.DatagramSocket#setReuseAddress(boolean) 178 */ 179 public MulticastSocket(int port) throws IOException { 180 this(new InetSocketAddress(port)); 181 } 182 183 /** 184 * Create a MulticastSocket bound to the specified socket address. 185 * <p> 186 * Or, if the address is {@code null}, create an unbound socket. 187 * 188 * <p>If there is a security manager, 189 * its {@code checkListen} method is first called 190 * with the SocketAddress port as its argument to ensure the operation is allowed. 191 * This could result in a SecurityException. 192 * <p> 193 * When the socket is created the 194 * {@link DatagramSocket#setReuseAddress(boolean)} method is 195 * called to enable the SO_REUSEADDR socket option. 196 * 197 * @param bindaddr Socket address to bind to, or {@code null} for 198 * an unbound socket. 199 * @throws IOException if an I/O exception occurs 200 * while creating the MulticastSocket 201 * @throws SecurityException if a security manager exists and its 202 * {@code checkListen} method doesn't allow the operation. 203 * @see SecurityManager#checkListen 204 * @see java.net.DatagramSocket#setReuseAddress(boolean) 205 * 206 * @since 1.4 207 */ 208 public MulticastSocket(SocketAddress bindaddr) throws IOException { 209 super((SocketAddress) null); 210 211 // Enable SO_REUSEADDR before binding 212 setReuseAddress(true); 213 214 if (bindaddr != null) { 215 try { 216 bind(bindaddr); 217 } finally { 218 if (!isBound()) { 219 close(); 220 } 221 } 222 } 223 } 224 225 /** 226 * The lock on the socket's TTL. This is for set/getTTL and 227 * send(packet,ttl). 228 */ 229 private Object ttlLock = new Object(); 230 231 /** 232 * The lock on the socket's interface - used by setInterface 233 * and getInterface 234 */ 235 private Object infLock = new Object(); 236 237 /** 238 * The "last" interface set by setInterface on this MulticastSocket 239 */ 240 private InetAddress infAddress = null; 241 242 243 /** 244 * Set the default time-to-live for multicast packets sent out 245 * on this {@code MulticastSocket} in order to control the 246 * scope of the multicasts. 247 * 248 * <p>The ttl is an <b>unsigned</b> 8-bit quantity, and so <B>must</B> be 249 * in the range {@code 0 <= ttl <= 0xFF }. 250 * 251 * @param ttl the time-to-live 252 * @throws IOException if an I/O exception occurs 253 * while setting the default time-to-live value 254 * @deprecated use the setTimeToLive method instead, which uses 255 * <b>int</b> instead of <b>byte</b> as the type for ttl. 256 * @see #getTTL() 257 */ 258 @Deprecated 259 public void setTTL(byte ttl) throws IOException { 260 if (isClosed()) 261 throw new SocketException("Socket is closed"); 262 getImpl().setTTL(ttl); 263 } 264 265 /** 266 * Set the default time-to-live for multicast packets sent out 267 * on this {@code MulticastSocket} in order to control the 268 * scope of the multicasts. 269 * 270 * <P> The ttl <B>must</B> be in the range {@code 0 <= ttl <= 271 * 255} or an {@code IllegalArgumentException} will be thrown. 272 * Multicast packets sent with a TTL of {@code 0} are not transmitted 273 * on the network but may be delivered locally. 274 * 275 * @param ttl 276 * the time-to-live 277 * 278 * @throws IOException 279 * if an I/O exception occurs while setting the 280 * default time-to-live value 281 * 282 * @see #getTimeToLive() 283 */ 284 public void setTimeToLive(int ttl) throws IOException { 285 if (ttl < 0 || ttl > 255) { 286 throw new IllegalArgumentException("ttl out of range"); 287 } 288 if (isClosed()) 289 throw new SocketException("Socket is closed"); 290 getImpl().setTimeToLive(ttl); 291 } 292 293 /** 294 * Get the default time-to-live for multicast packets sent out on 295 * the socket. 296 * 297 * @throws IOException if an I/O exception occurs 298 * while getting the default time-to-live value 299 * @return the default time-to-live value 300 * @deprecated use the getTimeToLive method instead, which returns 301 * an <b>int</b> instead of a <b>byte</b>. 302 * @see #setTTL(byte) 303 */ 304 @Deprecated 305 public byte getTTL() throws IOException { 306 if (isClosed()) 307 throw new SocketException("Socket is closed"); 308 return getImpl().getTTL(); 309 } 310 311 /** 312 * Get the default time-to-live for multicast packets sent out on 313 * the socket. 314 * @throws IOException if an I/O exception occurs while 315 * getting the default time-to-live value 316 * @return the default time-to-live value 317 * @see #setTimeToLive(int) 318 */ 319 public int getTimeToLive() throws IOException { 320 if (isClosed()) 321 throw new SocketException("Socket is closed"); 322 return getImpl().getTimeToLive(); 323 } 324 325 /** 326 * Joins a multicast group. Its behavior may be affected by 327 * {@code setInterface} or {@code setNetworkInterface}. 328 * 329 * <p>If there is a security manager, this method first 330 * calls its {@code checkMulticast} method with the 331 * {@code mcastaddr} argument as its argument. 332 * 333 * @param mcastaddr is the multicast address to join 334 * @throws IOException if there is an error joining, 335 * or when the address is not a multicast address, 336 * or the platform does not support multicasting 337 * @throws SecurityException if a security manager exists and its 338 * {@code checkMulticast} method doesn't allow the join. 339 * @deprecated This method does not accept the network interface on 340 * which to join the multicast group. Use 341 * {@link #joinGroup(SocketAddress, NetworkInterface)} instead. 342 * @see SecurityManager#checkMulticast(InetAddress) 343 */ 344 @Deprecated(since="14") 345 public void joinGroup(InetAddress mcastaddr) throws IOException { 346 if (isClosed()) { 347 throw new SocketException("Socket is closed"); 348 } 349 350 checkAddress(mcastaddr, "joinGroup"); 351 SecurityManager security = System.getSecurityManager(); 352 if (security != null) { 353 security.checkMulticast(mcastaddr); 354 } 355 356 if (!mcastaddr.isMulticastAddress()) { 357 throw new SocketException("Not a multicast address"); 358 } 359 360 /** 361 * required for some platforms where it's not possible to join 362 * a group without setting the interface first. 363 */ 364 NetworkInterface defaultInterface = NetworkInterface.getDefault(); 365 366 if (!interfaceSet && defaultInterface != null) { 367 setNetworkInterface(defaultInterface); 368 } 369 370 getImpl().join(mcastaddr); 371 } 372 373 /** 374 * Leave a multicast group. Its behavior may be affected by 375 * {@code setInterface} or {@code setNetworkInterface}. 376 * 377 * <p>If there is a security manager, this method first 378 * calls its {@code checkMulticast} method with the 379 * {@code mcastaddr} argument as its argument. 380 * 381 * @param mcastaddr is the multicast address to leave 382 * @throws IOException if there is an error leaving 383 * or when the address is not a multicast address. 384 * @throws SecurityException if a security manager exists and its 385 * {@code checkMulticast} method doesn't allow the operation. 386 * @deprecated This method does not accept the network interface on which 387 * to leave the multicast group. Use 388 * {@link #leaveGroup(SocketAddress, NetworkInterface)} instead. 389 * @see SecurityManager#checkMulticast(InetAddress) 390 */ 391 @Deprecated(since="14") 392 public void leaveGroup(InetAddress mcastaddr) throws IOException { 393 if (isClosed()) { 394 throw new SocketException("Socket is closed"); 395 } 396 397 checkAddress(mcastaddr, "leaveGroup"); 398 SecurityManager security = System.getSecurityManager(); 399 if (security != null) { 400 security.checkMulticast(mcastaddr); 401 } 402 403 if (!mcastaddr.isMulticastAddress()) { 404 throw new SocketException("Not a multicast address"); 405 } 406 407 getImpl().leave(mcastaddr); 408 } 409 410 /** 411 * Joins the specified multicast group at the specified interface. 412 * 413 * <p>If there is a security manager, this method first 414 * calls its {@code checkMulticast} method 415 * with the {@code mcastaddr} argument 416 * as its argument. 417 * 418 * @param mcastaddr is the multicast address to join 419 * @param netIf specifies the local interface to receive multicast 420 * datagram packets, or {@code null} to defer to the interface set by 421 * {@link MulticastSocket#setInterface(InetAddress)} or 422 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. 423 * If {@code null}, and no interface has been set, the behaviour is 424 * unspecified: any interface may be selected or the operation may fail 425 * with a {@code SocketException}. 426 * @throws IOException if there is an error joining, or when the address 427 * is not a multicast address, or the platform does not support 428 * multicasting 429 * @throws SecurityException if a security manager exists and its 430 * {@code checkMulticast} method doesn't allow the join. 431 * @throws IllegalArgumentException if mcastaddr is {@code null} or is a 432 * SocketAddress subclass not supported by this socket 433 * @see SecurityManager#checkMulticast(InetAddress) 434 * @since 1.4 435 */ 436 public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) 437 throws IOException { 438 if (isClosed()) 439 throw new SocketException("Socket is closed"); 440 441 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 442 throw new IllegalArgumentException("Unsupported address type"); 443 444 if (oldImpl) 445 throw new UnsupportedOperationException(); 446 447 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "joinGroup"); 448 SecurityManager security = System.getSecurityManager(); 449 if (security != null) { 450 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress()); 451 } 452 453 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) { 454 throw new SocketException("Not a multicast address"); 455 } 456 457 getImpl().joinGroup(mcastaddr, netIf); 458 } 459 460 /** 461 * Leave a multicast group on a specified local interface. 462 * 463 * <p>If there is a security manager, this method first 464 * calls its {@code checkMulticast} method with the 465 * {@code mcastaddr} argument as its argument. 466 * 467 * @param mcastaddr is the multicast address to leave 468 * @param netIf specifies the local interface or {@code null} to defer 469 * to the interface set by 470 * {@link MulticastSocket#setInterface(InetAddress)} or 471 * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. 472 * If {@code null}, and no interface has been set, the behaviour 473 * is unspecified: any interface may be selected or the operation 474 * may fail with a {@code SocketException}. 475 * @throws IOException if there is an error leaving or when the address 476 * is not a multicast address. 477 * @throws SecurityException if a security manager exists and its 478 * {@code checkMulticast} method doesn't allow the operation. 479 * @throws IllegalArgumentException if mcastaddr is {@code null} or is a 480 * SocketAddress subclass not supported by this socket. 481 * @see SecurityManager#checkMulticast(InetAddress) 482 * @since 1.4 483 */ 484 public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) 485 throws IOException { 486 if (isClosed()) 487 throw new SocketException("Socket is closed"); 488 489 if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) 490 throw new IllegalArgumentException("Unsupported address type"); 491 492 if (oldImpl) 493 throw new UnsupportedOperationException(); 494 495 checkAddress(((InetSocketAddress)mcastaddr).getAddress(), "leaveGroup"); 496 SecurityManager security = System.getSecurityManager(); 497 if (security != null) { 498 security.checkMulticast(((InetSocketAddress)mcastaddr).getAddress()); 499 } 500 501 if (!((InetSocketAddress)mcastaddr).getAddress().isMulticastAddress()) { 502 throw new SocketException("Not a multicast address"); 503 } 504 505 getImpl().leaveGroup(mcastaddr, netIf); 506 } 507 508 /** 509 * Set the multicast network interface used by methods 510 * whose behavior would be affected by the value of the 511 * network interface. Useful for multihomed hosts. 512 * 513 * @param inf the InetAddress 514 * @throws SocketException if there is an error in 515 * the underlying protocol, such as a TCP error. 516 * @deprecated The InetAddress may not uniquely identify 517 * the network interface. Use 518 * {@link #setNetworkInterface(NetworkInterface)} instead. 519 * @see #getInterface() 520 */ 521 @Deprecated(since="14") 522 public void setInterface(InetAddress inf) throws SocketException { 523 if (isClosed()) { 524 throw new SocketException("Socket is closed"); 525 } 526 checkAddress(inf, "setInterface"); 527 synchronized (infLock) { 528 getImpl().setOption(SocketOptions.IP_MULTICAST_IF, inf); 529 infAddress = inf; 530 interfaceSet = true; 531 } 532 } 533 534 /** 535 * Retrieve the address of the network interface used for 536 * multicast packets. 537 * 538 * @return An {@code InetAddress} representing the address 539 * of the network interface used for multicast packets, 540 * or if no interface has been set, an {@code InetAddress} 541 * representing any local address. 542 * @throws SocketException if there is an error in the 543 * underlying protocol, such as a TCP error. 544 * @deprecated The network interface may not be uniquely identified by 545 * the InetAddress returned. 546 * Use {@link #getNetworkInterface()} instead. 547 * @see #setInterface(java.net.InetAddress) 548 */ 549 @Deprecated(since="14") 550 public InetAddress getInterface() throws SocketException { 551 if (isClosed()) { 552 throw new SocketException("Socket is closed"); 553 } 554 synchronized (infLock) { 555 InetAddress ia = 556 (InetAddress)getImpl().getOption(SocketOptions.IP_MULTICAST_IF); 557 558 /** 559 * No previous setInterface or interface can be 560 * set using setNetworkInterface 561 */ 562 if (infAddress == null) { 563 return ia; 564 } 565 566 /** 567 * Same interface set with setInterface? 568 */ 569 if (ia.equals(infAddress)) { 570 return ia; 571 } 572 573 /** 574 * Different InetAddress from what we set with setInterface 575 * so enumerate the current interface to see if the 576 * address set by setInterface is bound to this interface. 577 */ 578 try { 579 NetworkInterface ni = NetworkInterface.getByInetAddress(ia); 580 Enumeration<InetAddress> addrs = ni.getInetAddresses(); 581 while (addrs.hasMoreElements()) { 582 InetAddress addr = addrs.nextElement(); 583 if (addr.equals(infAddress)) { 584 return infAddress; 585 } 586 } 587 588 /** 589 * No match so reset infAddress to indicate that the 590 * interface has changed via means 591 */ 592 infAddress = null; 593 return ia; 594 } catch (Exception e) { 595 return ia; 596 } 597 } 598 } 599 600 /** 601 * Specify the network interface for outgoing multicast datagrams 602 * sent on this socket. 603 * 604 * @param netIf the interface 605 * @throws SocketException if there is an error in 606 * the underlying protocol, such as a TCP error. 607 * @see #getNetworkInterface() 608 * @since 1.4 609 */ 610 public void setNetworkInterface(NetworkInterface netIf) 611 throws SocketException { 612 613 synchronized (infLock) { 614 getImpl().setOption(SocketOptions.IP_MULTICAST_IF2, netIf); 615 infAddress = null; 616 interfaceSet = true; 617 } 618 } 619 620 /** 621 * Get the multicast network interface set. 622 * 623 * @throws SocketException if there is an error in 624 * the underlying protocol, such as a TCP error. 625 * @return The multicast {@code NetworkInterface} currently set. A placeholder 626 * NetworkInterface is returned when there is no interface set; it has 627 * a single InetAddress to represent any local address. 628 * @see #setNetworkInterface(NetworkInterface) 629 * @since 1.4 630 */ 631 public NetworkInterface getNetworkInterface() throws SocketException { 632 NetworkInterface ni 633 = (NetworkInterface)getImpl().getOption(SocketOptions.IP_MULTICAST_IF2); 634 if (ni == null) { 635 InetAddress[] addrs = new InetAddress[1]; 636 addrs[0] = InetAddress.anyLocalAddress(); 637 return new NetworkInterface(addrs[0].getHostName(), 0, addrs); 638 } else { 639 return ni; 640 } 641 } 642 643 /** 644 * Disable/Enable local loopback of multicast datagrams 645 * The option is used by the platform's networking code as a hint 646 * for setting whether multicast data will be looped back to 647 * the local socket. 648 * 649 * <p>Because this option is a hint, applications that want to 650 * verify what loopback mode is set to should call 651 * {@link #getLoopbackMode()} 652 * @param disable {@code true} to disable the LoopbackMode 653 * @throws SocketException if an error occurs while setting the value 654 * @since 1.4 655 * @deprecated Use {@link #setOption(SocketOption, Object)} with 656 * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} 657 * instead. The loopback mode is enabled by default, 658 * {@code MulticastSocket.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false)} 659 * disables it. 660 * @see #getLoopbackMode 661 */ 662 @Deprecated(since="14") 663 public void setLoopbackMode(boolean disable) throws SocketException { 664 getImpl().setOption(SocketOptions.IP_MULTICAST_LOOP, Boolean.valueOf(disable)); 665 } 666 667 /** 668 * Get the setting for local loopback of multicast datagrams. 669 * 670 * @throws SocketException if an error occurs while getting the value 671 * @return true if the LoopbackMode has been disabled 672 * @since 1.4 673 * @deprecated Use {@link #getOption(SocketOption)} with 674 * {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP} 675 * instead. 676 * @see #setLoopbackMode 677 */ 678 @Deprecated(since="14") 679 public boolean getLoopbackMode() throws SocketException { 680 return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue(); 681 } 682 683 /** 684 * Sends a datagram packet to the destination, with a TTL (time- 685 * to-live) other than the default for the socket. This method 686 * need only be used in instances where a particular TTL is desired; 687 * otherwise it is preferable to set a TTL once on the socket, and 688 * use that default TTL for all packets. This method does <B>not 689 * </B> alter the default TTL for the socket. Its behavior may be 690 * affected by {@code setInterface}. 691 * 692 * <p>If there is a security manager, this method first performs some 693 * security checks. First, if {@code p.getAddress().isMulticastAddress()} 694 * is true, this method calls the 695 * security manager's {@code checkMulticast} method 696 * with {@code p.getAddress()} and {@code ttl} as its arguments. 697 * If the evaluation of that expression is false, 698 * this method instead calls the security manager's 699 * {@code checkConnect} method with arguments 700 * {@code p.getAddress().getHostAddress()} and 701 * {@code p.getPort()}. Each call to a security manager method 702 * could result in a SecurityException if the operation is not allowed. 703 * 704 * @param p is the packet to be sent. The packet should contain 705 * the destination multicast ip address and the data to be sent. 706 * One does not need to be the member of the group to send 707 * packets to a destination multicast address. 708 * @param ttl optional time to live for multicast packet. 709 * default ttl is 1. 710 * 711 * @throws IOException is raised if an error occurs i.e 712 * error while setting ttl. 713 * @throws SecurityException if a security manager exists and its 714 * {@code checkMulticast} or {@code checkConnect} 715 * method doesn't allow the send. 716 * @throws PortUnreachableException may be thrown if the socket is connected 717 * to a currently unreachable destination. Note, there is no 718 * guarantee that the exception will be thrown. 719 * @throws IllegalArgumentException if the socket is connected, 720 * and connected address and packet address differ, or 721 * if the socket is not connected and the packet address 722 * is not set. 723 * 724 * 725 * @deprecated Use the following code or its equivalent instead: 726 * ...... 727 * int ttl = mcastSocket.getTimeToLive(); 728 * mcastSocket.setTimeToLive(newttl); 729 * mcastSocket.send(p); 730 * mcastSocket.setTimeToLive(ttl); 731 * ...... 732 * 733 * @see DatagramSocket#send 734 * @see DatagramSocket#receive 735 * @see SecurityManager#checkMulticast(java.net.InetAddress, byte) 736 * @see SecurityManager#checkConnect 737 */ 738 @Deprecated 739 public void send(DatagramPacket p, byte ttl) 740 throws IOException { 741 if (isClosed()) 742 throw new SocketException("Socket is closed"); 743 synchronized(ttlLock) { 744 synchronized(p) { 745 InetAddress packetAddress = p.getAddress(); 746 checkAddress(packetAddress, "send"); 747 if (connectState == ST_NOT_CONNECTED) { 748 if (packetAddress == null) { 749 throw new IllegalArgumentException("Address not set"); 750 } 751 // Security manager makes sure that the multicast address 752 // is allowed one and that the ttl used is less 753 // than the allowed maxttl. 754 SecurityManager security = System.getSecurityManager(); 755 if (security != null) { 756 if (packetAddress.isMulticastAddress()) { 757 security.checkMulticast(packetAddress, ttl); 758 } else { 759 security.checkConnect(packetAddress.getHostAddress(), 760 p.getPort()); 761 } 762 } 763 } else { 764 // we're connected 765 if (packetAddress == null) { 766 p.setAddress(connectedAddress); 767 p.setPort(connectedPort); 768 } else if ((!packetAddress.equals(connectedAddress)) || 769 p.getPort() != connectedPort) { 770 throw new IllegalArgumentException("connected address and packet address" + 771 " differ"); 772 } 773 } 774 byte dttl = getTTL(); 775 try { 776 if (ttl != dttl) { 777 // set the ttl 778 getImpl().setTTL(ttl); 779 } 780 // call the datagram method to send 781 getImpl().send(p); 782 } finally { 783 // set it back to default 784 if (ttl != dttl) { 785 getImpl().setTTL(dttl); 786 } 787 } 788 } // synch p 789 } //synch ttl 790 } //method 791 792 private static Set<SocketOption<?>> options; 793 private static boolean optionsSet = false; 794 795 @Override 796 public Set<SocketOption<?>> supportedOptions() { 797 synchronized (MulticastSocket.class) { 798 if (optionsSet) { 799 return options; 800 } 801 try { 802 DatagramSocketImpl impl = getImpl(); 803 options = Collections.unmodifiableSet(impl.supportedOptions()); 804 } catch (SocketException ex) { 805 options = Collections.emptySet(); 806 } 807 optionsSet = true; 808 return options; 809 } 810 } 811 }