Frames | No Frames |
1: /* DatagramSocket.java -- A class to model UDP sockets 2: Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 3: Free Software Foundation, Inc. 4: 5: This file is part of GNU Classpath. 6: 7: GNU Classpath is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU Classpath is distributed in the hope that it will be useful, but 13: WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15: General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU Classpath; see the file COPYING. If not, write to the 19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20: 02110-1301 USA. 21: 22: Linking this library statically or dynamically with other modules is 23: making a combined work based on this library. Thus, the terms and 24: conditions of the GNU General Public License cover the whole 25: combination. 26: 27: As a special exception, the copyright holders of this library give you 28: permission to link this library with independent modules to produce an 29: executable, regardless of the license terms of these independent 30: modules, and to copy and distribute the resulting executable under 31: terms of your choice, provided that you also meet, for each linked 32: independent module, the terms and conditions of the license of that 33: module. An independent module is a module which is not derived from 34: or based on this library. If you modify this library, you may extend 35: this exception to your version of the library, but you are not 36: obligated to do so. If you do not wish to do so, delete this 37: exception statement from your version. */ 38: 39: package java.net; 40: 41: import gnu.classpath.SystemProperties; 42: 43: import gnu.java.net.PlainDatagramSocketImpl; 44: import gnu.java.nio.DatagramChannelImpl; 45: 46: import java.io.IOException; 47: import java.nio.channels.DatagramChannel; 48: import java.nio.channels.IllegalBlockingModeException; 49: 50: 51: /** 52: * Written using on-line Java Platform 1.2 API Specification, as well 53: * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998). 54: * Status: Believed complete and correct. 55: */ 56: /** 57: * This class models a connectionless datagram socket that sends 58: * individual packets of data across the network. In the TCP/IP world, 59: * this means UDP. Datagram packets do not have guaranteed delivery, 60: * or any guarantee about the order the data will be received on the 61: * remote host. 62: * 63: * @author Aaron M. Renn (arenn@urbanophile.com) 64: * @author Warren Levy (warrenl@cygnus.com) 65: * @date May 3, 1999. 66: */ 67: public class DatagramSocket 68: { 69: /** 70: * This is the user DatagramSocketImplFactory for this class. If this 71: * variable is null, a default factory is used. 72: */ 73: private static DatagramSocketImplFactory factory; 74: 75: /** 76: * This is the implementation object used by this socket. 77: */ 78: private DatagramSocketImpl impl; 79: 80: /** 81: * True if socket implementation was created. 82: */ 83: private boolean implCreated; 84: 85: /** 86: * This is the address we are "connected" to 87: */ 88: private InetAddress remoteAddress; 89: 90: /** 91: * This is the port we are "connected" to 92: */ 93: private int remotePort = -1; 94: 95: /** 96: * True if socket is bound. 97: */ 98: private boolean bound; 99: 100: /** 101: * Creates a <code>DatagramSocket</code> from a specified 102: * <code>DatagramSocketImpl</code> instance 103: * 104: * @param impl The <code>DatagramSocketImpl</code> the socket will be 105: * created from 106: * 107: * @since 1.4 108: */ 109: protected DatagramSocket(DatagramSocketImpl impl) 110: { 111: if (impl == null) 112: throw new NullPointerException("impl may not be null"); 113: 114: this.impl = impl; 115: this.remoteAddress = null; 116: this.remotePort = -1; 117: } 118: 119: /** 120: * Initializes a new instance of <code>DatagramSocket</code> that binds to 121: * a random port and every address on the local machine. 122: * 123: * @exception SocketException If an error occurs. 124: * @exception SecurityException If a security manager exists and 125: * its <code>checkListen</code> method doesn't allow the operation. 126: */ 127: public DatagramSocket() throws SocketException 128: { 129: this(new InetSocketAddress(0)); 130: } 131: 132: /** 133: * Initializes a new instance of <code>DatagramSocket</code> that binds to 134: * the specified port and every address on the local machine. 135: * 136: * @param port The local port number to bind to. 137: * 138: * @exception SecurityException If a security manager exists and its 139: * <code>checkListen</code> method doesn't allow the operation. 140: * @exception SocketException If an error occurs. 141: */ 142: public DatagramSocket(int port) throws SocketException 143: { 144: this(new InetSocketAddress(port)); 145: } 146: 147: /** 148: * Initializes a new instance of <code>DatagramSocket</code> that binds to 149: * the specified local port and address. 150: * 151: * @param port The local port number to bind to. 152: * @param addr The local address to bind to. 153: * 154: * @exception SecurityException If a security manager exists and its 155: * checkListen method doesn't allow the operation. 156: * @exception SocketException If an error occurs. 157: */ 158: public DatagramSocket(int port, InetAddress addr) throws SocketException 159: { 160: this(new InetSocketAddress(addr, port)); 161: } 162: 163: /** 164: * Initializes a new instance of <code>DatagramSocket</code> that binds to 165: * the specified local port and address. 166: * 167: * @param address The local address and port number to bind to. 168: * 169: * @exception SecurityException If a security manager exists and its 170: * <code>checkListen</code> method doesn't allow the operation. 171: * @exception SocketException If an error occurs. 172: * 173: * @since 1.4 174: */ 175: public DatagramSocket(SocketAddress address) throws SocketException 176: { 177: String propVal = SystemProperties.getProperty("impl.prefix"); 178: if (propVal == null || propVal.equals("")) 179: { 180: if (factory != null) 181: impl = factory.createDatagramSocketImpl(); 182: else 183: { 184: try 185: { 186: impl = new PlainDatagramSocketImpl(); 187: } 188: catch (IOException ioe) 189: { 190: SocketException se = new SocketException(); 191: se.initCause(ioe); 192: throw se; 193: } 194: } 195: } 196: else 197: try 198: { 199: impl = 200: (DatagramSocketImpl) Class.forName("java.net." + propVal 201: + "DatagramSocketImpl") 202: .newInstance(); 203: } 204: catch (Exception e) 205: { 206: System.err.println("Could not instantiate class: java.net." 207: + propVal + "DatagramSocketImpl"); 208: try 209: { 210: impl = new PlainDatagramSocketImpl(); 211: } 212: catch (IOException ioe) 213: { 214: SocketException se = new SocketException(); 215: se.initCause(ioe); 216: throw se; 217: } 218: } 219: 220: if (address != null) 221: bind(address); 222: } 223: 224: // This needs to be accessible from java.net.MulticastSocket 225: DatagramSocketImpl getImpl() throws SocketException 226: { 227: try 228: { 229: if (! implCreated) 230: { 231: impl.create(); 232: implCreated = true; 233: } 234: 235: return impl; 236: } 237: catch (IOException e) 238: { 239: SocketException se = new SocketException(); 240: se.initCause(e); 241: throw se; 242: } 243: } 244: 245: /** 246: * Closes this datagram socket. 247: */ 248: public void close() 249: { 250: if (isClosed()) 251: return; 252: 253: try 254: { 255: getImpl().close(); 256: } 257: catch (SocketException e) 258: { 259: // Ignore this case, just close the socket in finally clause. 260: } 261: finally 262: { 263: remoteAddress = null; 264: remotePort = -1; 265: impl = null; 266: } 267: 268: try 269: { 270: if (getChannel() != null) 271: getChannel().close(); 272: } 273: catch (IOException e) 274: { 275: // Do nothing. 276: } 277: } 278: 279: /** 280: * This method returns the remote address to which this socket is 281: * connected. If this socket is not connected, then this method will 282: * return <code>null</code>. 283: * 284: * @return The remote address. 285: * 286: * @since 1.2 287: */ 288: public InetAddress getInetAddress() 289: { 290: return remoteAddress; 291: } 292: 293: /** 294: * This method returns the remote port to which this socket is 295: * connected. If this socket is not connected, then this method will 296: * return -1. 297: * 298: * @return The remote port. 299: * 300: * @since 1.2 301: */ 302: public int getPort() 303: { 304: return remotePort; 305: } 306: 307: /** 308: * Returns the local address this datagram socket is bound to. 309: * 310: * @return The local address is the socket is bound or null 311: * 312: * @since 1.1 313: */ 314: public InetAddress getLocalAddress() 315: { 316: if (! isBound()) 317: return null; 318: 319: InetAddress localAddr; 320: 321: try 322: { 323: localAddr = 324: (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 325: 326: SecurityManager s = System.getSecurityManager(); 327: if (s != null) 328: s.checkConnect(localAddr.getHostAddress(), -1); 329: } 330: catch (SecurityException e) 331: { 332: localAddr = InetAddress.ANY_IF; 333: } 334: catch (SocketException e) 335: { 336: // This cannot happen as we are bound. 337: return null; 338: } 339: 340: return localAddr; 341: } 342: 343: /** 344: * Returns the local port this socket is bound to. 345: * 346: * @return The local port number. 347: */ 348: public int getLocalPort() 349: { 350: if (isClosed()) 351: return -1; 352: 353: try 354: { 355: return getImpl().getLocalPort(); 356: } 357: catch (SocketException e) 358: { 359: // This cannot happen as we are bound. 360: return 0; 361: } 362: } 363: 364: /** 365: * Returns the value of the socket's SO_TIMEOUT setting. If this method 366: * returns 0 then SO_TIMEOUT is disabled. 367: * 368: * @return The current timeout in milliseconds. 369: * 370: * @exception SocketException If an error occurs. 371: * 372: * @since 1.1 373: */ 374: public synchronized int getSoTimeout() throws SocketException 375: { 376: if (isClosed()) 377: throw new SocketException("socket is closed"); 378: 379: Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT); 380: 381: if (buf instanceof Integer) 382: return ((Integer) buf).intValue(); 383: 384: throw new SocketException("unexpected type"); 385: } 386: 387: /** 388: * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will 389: * disable SO_TIMEOUT. Any other value is the number of milliseconds 390: * a socket read/write will block before timing out. 391: * 392: * @param timeout The new SO_TIMEOUT value in milliseconds. 393: * 394: * @exception SocketException If an error occurs. 395: * 396: * @since 1.1 397: */ 398: public synchronized void setSoTimeout(int timeout) throws SocketException 399: { 400: if (isClosed()) 401: throw new SocketException("socket is closed"); 402: 403: if (timeout < 0) 404: throw new IllegalArgumentException("Invalid timeout: " + timeout); 405: 406: getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 407: } 408: 409: /** 410: * This method returns the value of the system level socket option 411: * SO_SNDBUF, which is used by the operating system to tune buffer 412: * sizes for data transfers. 413: * 414: * @return The send buffer size. 415: * 416: * @exception SocketException If an error occurs. 417: * 418: * @since 1.2 419: */ 420: public int getSendBufferSize() throws SocketException 421: { 422: if (isClosed()) 423: throw new SocketException("socket is closed"); 424: 425: Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); 426: 427: if (buf instanceof Integer) 428: return ((Integer) buf).intValue(); 429: 430: throw new SocketException("unexpected type"); 431: } 432: 433: /** 434: * This method sets the value for the system level socket option 435: * SO_SNDBUF to the specified value. Note that valid values for this 436: * option are specific to a given operating system. 437: * 438: * @param size The new send buffer size. 439: * 440: * @exception SocketException If an error occurs. 441: * @exception IllegalArgumentException If size is 0 or negative. 442: * 443: * @since 1.2 444: */ 445: public void setSendBufferSize(int size) throws SocketException 446: { 447: if (isClosed()) 448: throw new SocketException("socket is closed"); 449: 450: if (size < 0) 451: throw new IllegalArgumentException("Buffer size is less than 0"); 452: 453: getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 454: } 455: 456: /** 457: * This method returns the value of the system level socket option 458: * SO_RCVBUF, which is used by the operating system to tune buffer 459: * sizes for data transfers. 460: * 461: * @return The receive buffer size. 462: * 463: * @exception SocketException If an error occurs. 464: * 465: * @since 1.2 466: */ 467: public int getReceiveBufferSize() throws SocketException 468: { 469: if (isClosed()) 470: throw new SocketException("socket is closed"); 471: 472: Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); 473: 474: if (buf instanceof Integer) 475: return ((Integer) buf).intValue(); 476: 477: throw new SocketException("unexpected type"); 478: } 479: 480: /** 481: * This method sets the value for the system level socket option 482: * SO_RCVBUF to the specified value. Note that valid values for this 483: * option are specific to a given operating system. 484: * 485: * @param size The new receive buffer size. 486: * 487: * @exception SocketException If an error occurs. 488: * @exception IllegalArgumentException If size is 0 or negative. 489: * 490: * @since 1.2 491: */ 492: public void setReceiveBufferSize(int size) throws SocketException 493: { 494: if (isClosed()) 495: throw new SocketException("socket is closed"); 496: 497: if (size < 0) 498: throw new IllegalArgumentException("Buffer size is less than 0"); 499: 500: getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 501: } 502: 503: /** 504: * This method connects this socket to the specified address and port. 505: * When a datagram socket is connected, it will only send or receive 506: * packets to and from the host to which it is connected. A multicast 507: * socket that is connected may only send and not receive packets. 508: * 509: * @param address The address to connect this socket to. 510: * @param port The port to connect this socket to. 511: * 512: * @exception IllegalArgumentException If address or port are invalid. 513: * @exception SecurityException If the caller is not allowed to send 514: * datagrams to or receive from this address and port. 515: * 516: * @since 1.2 517: */ 518: public void connect(InetAddress address, int port) 519: { 520: if (address == null) 521: throw new IllegalArgumentException("Connect address may not be null"); 522: 523: if ((port < 1) || (port > 65535)) 524: throw new IllegalArgumentException("Port number is illegal: " + port); 525: 526: SecurityManager sm = System.getSecurityManager(); 527: if (sm != null) 528: { 529: if (address.isMulticastAddress()) 530: sm.checkMulticast(address); 531: else 532: { 533: sm.checkConnect(address.getHostAddress(), port); 534: sm.checkAccept(address.getHostAddress(), port); 535: } 536: } 537: 538: if (!isBound()) 539: { 540: try 541: { 542: bind(new InetSocketAddress(0)); 543: } 544: catch (SocketException e) 545: { 546: throw new Error("Binding socket failed.", e); 547: } 548: } 549: 550: try 551: { 552: getImpl().connect(address, port); 553: remoteAddress = address; 554: remotePort = port; 555: } 556: catch (SocketException e) 557: { 558: // This means simply not connected or connect not implemented. 559: } 560: } 561: 562: /** 563: * This method disconnects this socket from the address/port it was 564: * connected to. If the socket was not connected in the first place, 565: * this method does nothing. 566: * 567: * @since 1.2 568: */ 569: public void disconnect() 570: { 571: if (! isConnected()) 572: return; 573: 574: try 575: { 576: getImpl().disconnect(); 577: } 578: catch (SocketException e) 579: { 580: // This cannot happen as we are connected. 581: } 582: finally 583: { 584: remoteAddress = null; 585: remotePort = -1; 586: } 587: } 588: 589: /** 590: * Reads a datagram packet from the socket. Note that this method 591: * will block until a packet is received from the network. On return, 592: * the passed in <code>DatagramPacket</code> is populated with the data 593: * received and all the other information about the packet. 594: * 595: * @param p A <code>DatagramPacket</code> for storing the data 596: * 597: * @exception IOException If an error occurs. 598: * @exception SocketTimeoutException If setSoTimeout was previously called 599: * and the timeout has expired. 600: * @exception PortUnreachableException If the socket is connected to a 601: * currently unreachable destination. Note, there is no guarantee that the 602: * exception will be thrown. 603: * @exception IllegalBlockingModeException If this socket has an associated 604: * channel, and the channel is in non-blocking mode. 605: * @exception SecurityException If a security manager exists and its 606: * checkAccept method doesn't allow the receive. 607: */ 608: public synchronized void receive(DatagramPacket p) throws IOException 609: { 610: if (isClosed()) 611: throw new SocketException("socket is closed"); 612: 613: if (remoteAddress != null && remoteAddress.isMulticastAddress()) 614: throw new IOException 615: ("Socket connected to a multicast address my not receive"); 616: 617: if (getChannel() != null && ! getChannel().isBlocking() 618: && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 619: throw new IllegalBlockingModeException(); 620: 621: DatagramPacket p2 = new DatagramPacket(p.getData(), p.getOffset(), p.maxlen); 622: getImpl().receive(p2); 623: p.length = p2.length; 624: if (p2.getAddress() != null) 625: p.setAddress(p2.getAddress()); 626: if (p2.getPort() != -1) 627: p.setPort(p2.getPort()); 628: 629: SecurityManager s = System.getSecurityManager(); 630: if (s != null && isConnected()) 631: s.checkAccept(p.getAddress().getHostAddress(), p.getPort()); 632: } 633: 634: /** 635: * Sends the specified packet. The host and port to which the packet 636: * are to be sent should be set inside the packet. 637: * 638: * @param p The datagram packet to send. 639: * 640: * @exception IOException If an error occurs. 641: * @exception SecurityException If a security manager exists and its 642: * checkMulticast or checkConnect method doesn't allow the send. 643: * @exception PortUnreachableException If the socket is connected to a 644: * currently unreachable destination. Note, there is no guarantee that the 645: * exception will be thrown. 646: * @exception IllegalBlockingModeException If this socket has an associated 647: * channel, and the channel is in non-blocking mode. 648: */ 649: public void send(DatagramPacket p) throws IOException 650: { 651: if (isClosed()) 652: throw new SocketException("socket is closed"); 653: 654: // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api. 655: SecurityManager s = System.getSecurityManager(); 656: if (s != null && ! isConnected()) 657: { 658: InetAddress addr = p.getAddress(); 659: if (addr.isMulticastAddress()) 660: s.checkMulticast(addr); 661: else 662: s.checkConnect(addr.getHostAddress(), p.getPort()); 663: } 664: 665: if (isConnected()) 666: { 667: if (p.getAddress() != null 668: && (remoteAddress != p.getAddress() || remotePort != p.getPort())) 669: throw new IllegalArgumentException 670: ("DatagramPacket address does not match remote address"); 671: } 672: 673: // FIXME: if this is a subclass of MulticastSocket, 674: // use getTimeToLive for TTL val. 675: if (getChannel() != null && ! getChannel().isBlocking() 676: && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 677: throw new IllegalBlockingModeException(); 678: 679: getImpl().send(p); 680: } 681: 682: /** 683: * Binds the socket to the given socket address. 684: * 685: * @param address The socket address to bind to. 686: * 687: * @exception SocketException If an error occurs. 688: * @exception SecurityException If a security manager exists and 689: * its checkListen method doesn't allow the operation. 690: * @exception IllegalArgumentException If address type is not supported. 691: * 692: * @since 1.4 693: */ 694: public void bind(SocketAddress address) throws SocketException 695: { 696: if (isClosed()) 697: throw new SocketException("socket is closed"); 698: 699: if (address == null) 700: address = new InetSocketAddress(InetAddress.ANY_IF, 0); 701: 702: if (! (address instanceof InetSocketAddress)) 703: throw new IllegalArgumentException("unsupported address type"); 704: 705: InetAddress addr = ((InetSocketAddress) address).getAddress(); 706: int port = ((InetSocketAddress) address).getPort(); 707: 708: if (port < 0 || port > 65535) 709: throw new IllegalArgumentException("Invalid port: " + port); 710: 711: SecurityManager s = System.getSecurityManager(); 712: if (s != null) 713: s.checkListen(port); 714: 715: if (addr == null) 716: addr = InetAddress.ANY_IF; 717: 718: try 719: { 720: getImpl().bind(port, addr); 721: bound = true; 722: } 723: catch (SocketException exception) 724: { 725: getImpl().close(); 726: throw exception; 727: } 728: catch (RuntimeException exception) 729: { 730: getImpl().close(); 731: throw exception; 732: } 733: catch (Error error) 734: { 735: getImpl().close(); 736: throw error; 737: } 738: } 739: 740: /** 741: * Checks if the datagram socket is closed. 742: * 743: * @return True if socket is closed, false otherwise. 744: * 745: * @since 1.4 746: */ 747: public boolean isClosed() 748: { 749: return impl == null; 750: } 751: 752: /** 753: * Returns the datagram channel assoziated with this datagram socket. 754: * 755: * @return The associated <code>DatagramChannel</code> object or null 756: * 757: * @since 1.4 758: */ 759: public DatagramChannel getChannel() 760: { 761: return null; 762: } 763: 764: /** 765: * Connects the datagram socket to a specified socket address. 766: * 767: * @param address The socket address to connect to. 768: * 769: * @exception SocketException If an error occurs. 770: * @exception IllegalArgumentException If address type is not supported. 771: * 772: * @since 1.4 773: */ 774: public void connect(SocketAddress address) throws SocketException 775: { 776: if (isClosed()) 777: throw new SocketException("socket is closed"); 778: 779: if (! (address instanceof InetSocketAddress)) 780: throw new IllegalArgumentException("unsupported address type"); 781: 782: InetSocketAddress tmp = (InetSocketAddress) address; 783: connect(tmp.getAddress(), tmp.getPort()); 784: } 785: 786: /** 787: * Returns the binding state of the socket. 788: * 789: * @return True if socket bound, false otherwise. 790: * 791: * @since 1.4 792: */ 793: public boolean isBound() 794: { 795: return bound; 796: } 797: 798: /** 799: * Returns the connection state of the socket. 800: * 801: * @return True if socket is connected, false otherwise. 802: * 803: * @since 1.4 804: */ 805: public boolean isConnected() 806: { 807: return remoteAddress != null; 808: } 809: 810: /** 811: * Returns the SocketAddress of the host this socket is conneted to 812: * or null if this socket is not connected. 813: * 814: * @return The socket address of the remote host if connected or null 815: * 816: * @since 1.4 817: */ 818: public SocketAddress getRemoteSocketAddress() 819: { 820: if (! isConnected()) 821: return null; 822: 823: return new InetSocketAddress(remoteAddress, remotePort); 824: } 825: 826: /** 827: * Returns the local SocketAddress this socket is bound to. 828: * 829: * @return The local SocketAddress or null if the socket is not bound. 830: * 831: * @since 1.4 832: */ 833: public SocketAddress getLocalSocketAddress() 834: { 835: if (! isBound()) 836: return null; 837: 838: return new InetSocketAddress(getLocalAddress(), getLocalPort()); 839: } 840: 841: /** 842: * Enables/Disables SO_REUSEADDR. 843: * 844: * @param on Whether or not to have SO_REUSEADDR turned on. 845: * 846: * @exception SocketException If an error occurs. 847: * 848: * @since 1.4 849: */ 850: public void setReuseAddress(boolean on) throws SocketException 851: { 852: if (isClosed()) 853: throw new SocketException("socket is closed"); 854: 855: getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 856: } 857: 858: /** 859: * Checks if SO_REUSEADDR is enabled. 860: * 861: * @return True if SO_REUSEADDR is set on the socket, false otherwise. 862: * 863: * @exception SocketException If an error occurs. 864: * 865: * @since 1.4 866: */ 867: public boolean getReuseAddress() throws SocketException 868: { 869: if (isClosed()) 870: throw new SocketException("socket is closed"); 871: 872: Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR); 873: 874: if (buf instanceof Boolean) 875: return ((Boolean) buf).booleanValue(); 876: 877: throw new SocketException("unexpected type"); 878: } 879: 880: /** 881: * Enables/Disables SO_BROADCAST 882: * 883: * @param enable True if SO_BROADCAST should be enabled, false otherwise. 884: * 885: * @exception SocketException If an error occurs 886: * 887: * @since 1.4 888: */ 889: public void setBroadcast(boolean enable) throws SocketException 890: { 891: if (isClosed()) 892: throw new SocketException("socket is closed"); 893: 894: getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable)); 895: } 896: 897: /** 898: * Checks if SO_BROADCAST is enabled 899: * 900: * @return Whether SO_BROADCAST is set 901: * 902: * @exception SocketException If an error occurs 903: * 904: * @since 1.4 905: */ 906: public boolean getBroadcast() throws SocketException 907: { 908: if (isClosed()) 909: throw new SocketException("socket is closed"); 910: 911: Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST); 912: 913: if (buf instanceof Boolean) 914: return ((Boolean) buf).booleanValue(); 915: 916: throw new SocketException("unexpected type"); 917: } 918: 919: /** 920: * Sets the traffic class value 921: * 922: * @param tc The traffic class 923: * 924: * @exception SocketException If an error occurs 925: * @exception IllegalArgumentException If tc value is illegal 926: * 927: * @see DatagramSocket#getTrafficClass() 928: * 929: * @since 1.4 930: */ 931: public void setTrafficClass(int tc) throws SocketException 932: { 933: if (isClosed()) 934: throw new SocketException("socket is closed"); 935: 936: if (tc < 0 || tc > 255) 937: throw new IllegalArgumentException(); 938: 939: getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc)); 940: } 941: 942: /** 943: * Returns the current traffic class 944: * 945: * @return The current traffic class. 946: * 947: * @see DatagramSocket#setTrafficClass(int tc) 948: * 949: * @exception SocketException If an error occurs 950: * 951: * @since 1.4 952: */ 953: public int getTrafficClass() throws SocketException 954: { 955: if (isClosed()) 956: throw new SocketException("socket is closed"); 957: 958: Object buf = getImpl().getOption(SocketOptions.IP_TOS); 959: 960: if (buf instanceof Integer) 961: return ((Integer) buf).intValue(); 962: 963: throw new SocketException("unexpected type"); 964: } 965: 966: /** 967: * Sets the datagram socket implementation factory for the application 968: * 969: * @param fac The factory to set 970: * 971: * @exception IOException If an error occurs 972: * @exception SocketException If the factory is already defined 973: * @exception SecurityException If a security manager exists and its 974: * checkSetFactory method doesn't allow the operation 975: */ 976: public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 977: throws IOException 978: { 979: if (factory != null) 980: throw new SocketException("DatagramSocketImplFactory already defined"); 981: 982: SecurityManager sm = System.getSecurityManager(); 983: if (sm != null) 984: sm.checkSetFactory(); 985: 986: factory = fac; 987: } 988: }