Frames | No Frames |
1: /* DatagramSocket.java -- A class to model UDP sockets 2: Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005 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: impl = new PlainDatagramSocketImpl(); 184: } 185: else 186: try 187: { 188: impl = 189: (DatagramSocketImpl) Class.forName("java.net." + propVal 190: + "DatagramSocketImpl") 191: .newInstance(); 192: } 193: catch (Exception e) 194: { 195: System.err.println("Could not instantiate class: java.net." 196: + propVal + "DatagramSocketImpl"); 197: impl = new PlainDatagramSocketImpl(); 198: } 199: 200: if (address != null) 201: bind(address); 202: } 203: 204: // This needs to be accessible from java.net.MulticastSocket 205: DatagramSocketImpl getImpl() throws SocketException 206: { 207: try 208: { 209: if (! implCreated) 210: { 211: impl.create(); 212: implCreated = true; 213: } 214: 215: return impl; 216: } 217: catch (IOException e) 218: { 219: SocketException se = new SocketException(); 220: se.initCause(e); 221: throw se; 222: } 223: } 224: 225: /** 226: * Closes this datagram socket. 227: */ 228: public void close() 229: { 230: if (isClosed()) 231: return; 232: 233: try 234: { 235: getImpl().close(); 236: } 237: catch (SocketException e) 238: { 239: // Ignore this case, just close the socket in finally clause. 240: } 241: finally 242: { 243: remoteAddress = null; 244: remotePort = -1; 245: impl = null; 246: } 247: 248: try 249: { 250: if (getChannel() != null) 251: getChannel().close(); 252: } 253: catch (IOException e) 254: { 255: // Do nothing. 256: } 257: } 258: 259: /** 260: * This method returns the remote address to which this socket is 261: * connected. If this socket is not connected, then this method will 262: * return <code>null</code>. 263: * 264: * @return The remote address. 265: * 266: * @since 1.2 267: */ 268: public InetAddress getInetAddress() 269: { 270: return remoteAddress; 271: } 272: 273: /** 274: * This method returns the remote port to which this socket is 275: * connected. If this socket is not connected, then this method will 276: * return -1. 277: * 278: * @return The remote port. 279: * 280: * @since 1.2 281: */ 282: public int getPort() 283: { 284: return remotePort; 285: } 286: 287: /** 288: * Returns the local address this datagram socket is bound to. 289: * 290: * @return The local address is the socket is bound or null 291: * 292: * @since 1.1 293: */ 294: public InetAddress getLocalAddress() 295: { 296: if (! isBound()) 297: return null; 298: 299: InetAddress localAddr; 300: 301: try 302: { 303: localAddr = 304: (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 305: 306: SecurityManager s = System.getSecurityManager(); 307: if (s != null) 308: s.checkConnect(localAddr.getHostName(), -1); 309: } 310: catch (SecurityException e) 311: { 312: localAddr = InetAddress.ANY_IF; 313: } 314: catch (SocketException e) 315: { 316: // This cannot happen as we are bound. 317: return null; 318: } 319: 320: return localAddr; 321: } 322: 323: /** 324: * Returns the local port this socket is bound to. 325: * 326: * @return The local port number. 327: */ 328: public int getLocalPort() 329: { 330: if (isClosed()) 331: return -1; 332: 333: try 334: { 335: return getImpl().getLocalPort(); 336: } 337: catch (SocketException e) 338: { 339: // This cannot happen as we are bound. 340: return 0; 341: } 342: } 343: 344: /** 345: * Returns the value of the socket's SO_TIMEOUT setting. If this method 346: * returns 0 then SO_TIMEOUT is disabled. 347: * 348: * @return The current timeout in milliseconds. 349: * 350: * @exception SocketException If an error occurs. 351: * 352: * @since 1.1 353: */ 354: public synchronized int getSoTimeout() throws SocketException 355: { 356: if (isClosed()) 357: throw new SocketException("socket is closed"); 358: 359: Object buf = getImpl().getOption(SocketOptions.SO_TIMEOUT); 360: 361: if (buf instanceof Integer) 362: return ((Integer) buf).intValue(); 363: 364: throw new SocketException("unexpected type"); 365: } 366: 367: /** 368: * Sets the value of the socket's SO_TIMEOUT value. A value of 0 will 369: * disable SO_TIMEOUT. Any other value is the number of milliseconds 370: * a socket read/write will block before timing out. 371: * 372: * @param timeout The new SO_TIMEOUT value in milliseconds. 373: * 374: * @exception SocketException If an error occurs. 375: * 376: * @since 1.1 377: */ 378: public synchronized void setSoTimeout(int timeout) throws SocketException 379: { 380: if (isClosed()) 381: throw new SocketException("socket is closed"); 382: 383: if (timeout < 0) 384: throw new IllegalArgumentException("Invalid timeout: " + timeout); 385: 386: getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); 387: } 388: 389: /** 390: * This method returns the value of the system level socket option 391: * SO_SNDBUF, which is used by the operating system to tune buffer 392: * sizes for data transfers. 393: * 394: * @return The send buffer size. 395: * 396: * @exception SocketException If an error occurs. 397: * 398: * @since 1.2 399: */ 400: public int getSendBufferSize() throws SocketException 401: { 402: if (isClosed()) 403: throw new SocketException("socket is closed"); 404: 405: Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); 406: 407: if (buf instanceof Integer) 408: return ((Integer) buf).intValue(); 409: 410: throw new SocketException("unexpected type"); 411: } 412: 413: /** 414: * This method sets the value for the system level socket option 415: * SO_SNDBUF to the specified value. Note that valid values for this 416: * option are specific to a given operating system. 417: * 418: * @param size The new send buffer size. 419: * 420: * @exception SocketException If an error occurs. 421: * @exception IllegalArgumentException If size is 0 or negative. 422: * 423: * @since 1.2 424: */ 425: public void setSendBufferSize(int size) throws SocketException 426: { 427: if (isClosed()) 428: throw new SocketException("socket is closed"); 429: 430: if (size < 0) 431: throw new IllegalArgumentException("Buffer size is less than 0"); 432: 433: getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); 434: } 435: 436: /** 437: * This method returns the value of the system level socket option 438: * SO_RCVBUF, which is used by the operating system to tune buffer 439: * sizes for data transfers. 440: * 441: * @return The receive buffer size. 442: * 443: * @exception SocketException If an error occurs. 444: * 445: * @since 1.2 446: */ 447: public int getReceiveBufferSize() throws SocketException 448: { 449: if (isClosed()) 450: throw new SocketException("socket is closed"); 451: 452: Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); 453: 454: if (buf instanceof Integer) 455: return ((Integer) buf).intValue(); 456: 457: throw new SocketException("unexpected type"); 458: } 459: 460: /** 461: * This method sets the value for the system level socket option 462: * SO_RCVBUF to the specified value. Note that valid values for this 463: * option are specific to a given operating system. 464: * 465: * @param size The new receive buffer size. 466: * 467: * @exception SocketException If an error occurs. 468: * @exception IllegalArgumentException If size is 0 or negative. 469: * 470: * @since 1.2 471: */ 472: public void setReceiveBufferSize(int size) throws SocketException 473: { 474: if (isClosed()) 475: throw new SocketException("socket is closed"); 476: 477: if (size < 0) 478: throw new IllegalArgumentException("Buffer size is less than 0"); 479: 480: getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size)); 481: } 482: 483: /** 484: * This method connects this socket to the specified address and port. 485: * When a datagram socket is connected, it will only send or receive 486: * packets to and from the host to which it is connected. A multicast 487: * socket that is connected may only send and not receive packets. 488: * 489: * @param address The address to connect this socket to. 490: * @param port The port to connect this socket to. 491: * 492: * @exception IllegalArgumentException If address or port are invalid. 493: * @exception SecurityException If the caller is not allowed to send 494: * datagrams to or receive from this address and port. 495: * 496: * @since 1.2 497: */ 498: public void connect(InetAddress address, int port) 499: { 500: if (address == null) 501: throw new IllegalArgumentException("Connect address may not be null"); 502: 503: if ((port < 1) || (port > 65535)) 504: throw new IllegalArgumentException("Port number is illegal: " + port); 505: 506: SecurityManager sm = System.getSecurityManager(); 507: if (sm != null) 508: sm.checkConnect(address.getHostName(), port); 509: 510: try 511: { 512: getImpl().connect(address, port); 513: remoteAddress = address; 514: remotePort = port; 515: } 516: catch (SocketException e) 517: { 518: // This means simply not connected or connect not implemented. 519: } 520: } 521: 522: /** 523: * This method disconnects this socket from the address/port it was 524: * connected to. If the socket was not connected in the first place, 525: * this method does nothing. 526: * 527: * @since 1.2 528: */ 529: public void disconnect() 530: { 531: if (! isConnected()) 532: return; 533: 534: try 535: { 536: getImpl().disconnect(); 537: } 538: catch (SocketException e) 539: { 540: // This cannot happen as we are connected. 541: } 542: finally 543: { 544: remoteAddress = null; 545: remotePort = -1; 546: } 547: } 548: 549: /** 550: * Reads a datagram packet from the socket. Note that this method 551: * will block until a packet is received from the network. On return, 552: * the passed in <code>DatagramPacket</code> is populated with the data 553: * received and all the other information about the packet. 554: * 555: * @param p A <code>DatagramPacket</code> for storing the data 556: * 557: * @exception IOException If an error occurs. 558: * @exception SocketTimeoutException If setSoTimeout was previously called 559: * and the timeout has expired. 560: * @exception PortUnreachableException If the socket is connected to a 561: * currently unreachable destination. Note, there is no guarantee that the 562: * exception will be thrown. 563: * @exception IllegalBlockingModeException If this socket has an associated 564: * channel, and the channel is in non-blocking mode. 565: * @exception SecurityException If a security manager exists and its 566: * checkAccept method doesn't allow the receive. 567: */ 568: public synchronized void receive(DatagramPacket p) throws IOException 569: { 570: if (isClosed()) 571: throw new SocketException("socket is closed"); 572: 573: if (remoteAddress != null && remoteAddress.isMulticastAddress()) 574: throw new IOException 575: ("Socket connected to a multicast address my not receive"); 576: 577: if (getChannel() != null && ! getChannel().isBlocking() 578: && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 579: throw new IllegalBlockingModeException(); 580: 581: getImpl().receive(p); 582: 583: SecurityManager s = System.getSecurityManager(); 584: if (s != null && isConnected()) 585: s.checkAccept(p.getAddress().getHostName(), p.getPort()); 586: } 587: 588: /** 589: * Sends the specified packet. The host and port to which the packet 590: * are to be sent should be set inside the packet. 591: * 592: * @param p The datagram packet to send. 593: * 594: * @exception IOException If an error occurs. 595: * @exception SecurityException If a security manager exists and its 596: * checkMulticast or checkConnect method doesn't allow the send. 597: * @exception PortUnreachableException If the socket is connected to a 598: * currently unreachable destination. Note, there is no guarantee that the 599: * exception will be thrown. 600: * @exception IllegalBlockingModeException If this socket has an associated 601: * channel, and the channel is in non-blocking mode. 602: */ 603: public void send(DatagramPacket p) throws IOException 604: { 605: if (isClosed()) 606: throw new SocketException("socket is closed"); 607: 608: // JDK1.2: Don't do security checks if socket is connected; see jdk1.2 api. 609: SecurityManager s = System.getSecurityManager(); 610: if (s != null && ! isConnected()) 611: { 612: InetAddress addr = p.getAddress(); 613: if (addr.isMulticastAddress()) 614: s.checkMulticast(addr); 615: else 616: s.checkConnect(addr.getHostAddress(), p.getPort()); 617: } 618: 619: if (isConnected()) 620: { 621: if (p.getAddress() != null 622: && (remoteAddress != p.getAddress() || remotePort != p.getPort())) 623: throw new IllegalArgumentException 624: ("DatagramPacket address does not match remote address"); 625: } 626: 627: // FIXME: if this is a subclass of MulticastSocket, 628: // use getTimeToLive for TTL val. 629: if (getChannel() != null && ! getChannel().isBlocking() 630: && ! ((DatagramChannelImpl) getChannel()).isInChannelOperation()) 631: throw new IllegalBlockingModeException(); 632: 633: getImpl().send(p); 634: } 635: 636: /** 637: * Binds the socket to the given socket address. 638: * 639: * @param address The socket address to bind to. 640: * 641: * @exception SocketException If an error occurs. 642: * @exception SecurityException If a security manager exists and 643: * its checkListen method doesn't allow the operation. 644: * @exception IllegalArgumentException If address type is not supported. 645: * 646: * @since 1.4 647: */ 648: public void bind(SocketAddress address) throws SocketException 649: { 650: if (isClosed()) 651: throw new SocketException("socket is closed"); 652: 653: if (! (address instanceof InetSocketAddress)) 654: throw new IllegalArgumentException("unsupported address type"); 655: 656: InetAddress addr = ((InetSocketAddress) address).getAddress(); 657: int port = ((InetSocketAddress) address).getPort(); 658: 659: if (port < 0 || port > 65535) 660: throw new IllegalArgumentException("Invalid port: " + port); 661: 662: SecurityManager s = System.getSecurityManager(); 663: if (s != null) 664: s.checkListen(port); 665: 666: if (addr == null) 667: addr = InetAddress.ANY_IF; 668: 669: try 670: { 671: getImpl().bind(port, addr); 672: bound = true; 673: } 674: catch (SocketException exception) 675: { 676: getImpl().close(); 677: throw exception; 678: } 679: catch (RuntimeException exception) 680: { 681: getImpl().close(); 682: throw exception; 683: } 684: catch (Error error) 685: { 686: getImpl().close(); 687: throw error; 688: } 689: } 690: 691: /** 692: * Checks if the datagram socket is closed. 693: * 694: * @return True if socket is closed, false otherwise. 695: * 696: * @since 1.4 697: */ 698: public boolean isClosed() 699: { 700: return impl == null; 701: } 702: 703: /** 704: * Returns the datagram channel assoziated with this datagram socket. 705: * 706: * @return The associated <code>DatagramChannel</code> object or null 707: * 708: * @since 1.4 709: */ 710: public DatagramChannel getChannel() 711: { 712: return null; 713: } 714: 715: /** 716: * Connects the datagram socket to a specified socket address. 717: * 718: * @param address The socket address to connect to. 719: * 720: * @exception SocketException If an error occurs. 721: * @exception IllegalArgumentException If address type is not supported. 722: * 723: * @since 1.4 724: */ 725: public void connect(SocketAddress address) throws SocketException 726: { 727: if (isClosed()) 728: throw new SocketException("socket is closed"); 729: 730: if (! (address instanceof InetSocketAddress)) 731: throw new IllegalArgumentException("unsupported address type"); 732: 733: InetSocketAddress tmp = (InetSocketAddress) address; 734: connect(tmp.getAddress(), tmp.getPort()); 735: } 736: 737: /** 738: * Returns the binding state of the socket. 739: * 740: * @return True if socket bound, false otherwise. 741: * 742: * @since 1.4 743: */ 744: public boolean isBound() 745: { 746: return bound; 747: } 748: 749: /** 750: * Returns the connection state of the socket. 751: * 752: * @return True if socket is connected, false otherwise. 753: * 754: * @since 1.4 755: */ 756: public boolean isConnected() 757: { 758: return remoteAddress != null; 759: } 760: 761: /** 762: * Returns the SocketAddress of the host this socket is conneted to 763: * or null if this socket is not connected. 764: * 765: * @return The socket address of the remote host if connected or null 766: * 767: * @since 1.4 768: */ 769: public SocketAddress getRemoteSocketAddress() 770: { 771: if (! isConnected()) 772: return null; 773: 774: return new InetSocketAddress(remoteAddress, remotePort); 775: } 776: 777: /** 778: * Returns the local SocketAddress this socket is bound to. 779: * 780: * @return The local SocketAddress or null if the socket is not bound. 781: * 782: * @since 1.4 783: */ 784: public SocketAddress getLocalSocketAddress() 785: { 786: if (! isBound()) 787: return null; 788: 789: return new InetSocketAddress(getLocalAddress(), getLocalPort()); 790: } 791: 792: /** 793: * Enables/Disables SO_REUSEADDR. 794: * 795: * @param on Whether or not to have SO_REUSEADDR turned on. 796: * 797: * @exception SocketException If an error occurs. 798: * 799: * @since 1.4 800: */ 801: public void setReuseAddress(boolean on) throws SocketException 802: { 803: if (isClosed()) 804: throw new SocketException("socket is closed"); 805: 806: getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on)); 807: } 808: 809: /** 810: * Checks if SO_REUSEADDR is enabled. 811: * 812: * @return True if SO_REUSEADDR is set on the socket, false otherwise. 813: * 814: * @exception SocketException If an error occurs. 815: * 816: * @since 1.4 817: */ 818: public boolean getReuseAddress() throws SocketException 819: { 820: if (isClosed()) 821: throw new SocketException("socket is closed"); 822: 823: Object buf = getImpl().getOption(SocketOptions.SO_REUSEADDR); 824: 825: if (buf instanceof Boolean) 826: return ((Boolean) buf).booleanValue(); 827: 828: throw new SocketException("unexpected type"); 829: } 830: 831: /** 832: * Enables/Disables SO_BROADCAST 833: * 834: * @param enable True if SO_BROADCAST should be enabled, false otherwise. 835: * 836: * @exception SocketException If an error occurs 837: * 838: * @since 1.4 839: */ 840: public void setBroadcast(boolean enable) throws SocketException 841: { 842: if (isClosed()) 843: throw new SocketException("socket is closed"); 844: 845: getImpl().setOption(SocketOptions.SO_BROADCAST, Boolean.valueOf(enable)); 846: } 847: 848: /** 849: * Checks if SO_BROADCAST is enabled 850: * 851: * @return Whether SO_BROADCAST is set 852: * 853: * @exception SocketException If an error occurs 854: * 855: * @since 1.4 856: */ 857: public boolean getBroadcast() throws SocketException 858: { 859: if (isClosed()) 860: throw new SocketException("socket is closed"); 861: 862: Object buf = getImpl().getOption(SocketOptions.SO_BROADCAST); 863: 864: if (buf instanceof Boolean) 865: return ((Boolean) buf).booleanValue(); 866: 867: throw new SocketException("unexpected type"); 868: } 869: 870: /** 871: * Sets the traffic class value 872: * 873: * @param tc The traffic class 874: * 875: * @exception SocketException If an error occurs 876: * @exception IllegalArgumentException If tc value is illegal 877: * 878: * @see DatagramSocket#getTrafficClass() 879: * 880: * @since 1.4 881: */ 882: public void setTrafficClass(int tc) throws SocketException 883: { 884: if (isClosed()) 885: throw new SocketException("socket is closed"); 886: 887: if (tc < 0 || tc > 255) 888: throw new IllegalArgumentException(); 889: 890: getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); 891: } 892: 893: /** 894: * Returns the current traffic class 895: * 896: * @return The current traffic class. 897: * 898: * @see DatagramSocket#setTrafficClass(int tc) 899: * 900: * @exception SocketException If an error occurs 901: * 902: * @since 1.4 903: */ 904: public int getTrafficClass() throws SocketException 905: { 906: if (isClosed()) 907: throw new SocketException("socket is closed"); 908: 909: Object buf = getImpl().getOption(SocketOptions.IP_TOS); 910: 911: if (buf instanceof Integer) 912: return ((Integer) buf).intValue(); 913: 914: throw new SocketException("unexpected type"); 915: } 916: 917: /** 918: * Sets the datagram socket implementation factory for the application 919: * 920: * @param fac The factory to set 921: * 922: * @exception IOException If an error occurs 923: * @exception SocketException If the factory is already defined 924: * @exception SecurityException If a security manager exists and its 925: * checkSetFactory method doesn't allow the operation 926: */ 927: public static void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) 928: throws IOException 929: { 930: if (factory != null) 931: throw new SocketException("DatagramSocketImplFactory already defined"); 932: 933: SecurityManager sm = System.getSecurityManager(); 934: if (sm != null) 935: sm.checkSetFactory(); 936: 937: factory = fac; 938: } 939: }