Frames | No Frames |
1: /* Socket.java -- Client socket implementation 2: Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007 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.java.net.PlainSocketImpl; 42: 43: import java.io.IOException; 44: import java.io.InputStream; 45: import java.io.OutputStream; 46: import java.nio.channels.IllegalBlockingModeException; 47: import java.nio.channels.SocketChannel; 48: 49: 50: /* Written using on-line Java Platform 1.2 API Specification. 51: * Status: I believe all methods are implemented. 52: */ 53: 54: /** 55: * This class models a client site socket. A socket is a TCP/IP endpoint 56: * for network communications conceptually similar to a file handle. 57: * <p> 58: * This class does not actually do any work. Instead, it redirects all of 59: * its calls to a socket implementation object which implements the 60: * <code>SocketImpl</code> interface. The implementation class is 61: * instantiated by factory class that implements the 62: * <code>SocketImplFactory interface</code>. A default 63: * factory is provided, however the factory may be set by a call to 64: * the <code>setSocketImplFactory</code> method. Note that this may only be 65: * done once per virtual machine. If a subsequent attempt is made to set the 66: * factory, a <code>SocketException</code> will be thrown. 67: * 68: * @author Aaron M. Renn (arenn@urbanophile.com) 69: * @author Per Bothner (bothner@cygnus.com) 70: */ 71: public class Socket 72: { 73: /** 74: * This is the user SocketImplFactory for this class. If this variable is 75: * null, a default factory is used. 76: */ 77: static SocketImplFactory factory; 78: 79: /** 80: * The implementation object to which calls are redirected 81: */ 82: // package-private because ServerSocket.implAccept() needs to access it. 83: SocketImpl impl; 84: 85: /** 86: * True if impl.create() has been called. 87: */ 88: // package-private because ServerSocket.implAccept() needs to access it. 89: boolean implCreated; 90: 91: /** 92: * True if the socket is bound. 93: * Package private so it can be set from ServerSocket when accept is called. 94: */ 95: boolean bound; 96: 97: /** 98: * True if input is shutdown. 99: */ 100: private boolean inputShutdown; 101: 102: /** 103: * True if output is shutdown. 104: */ 105: private boolean outputShutdown; 106: 107: /** 108: * Initializes a new instance of <code>Socket</code> object without 109: * connecting to a remote host. This useful for subclasses of socket that 110: * might want this behavior. 111: * 112: * @specnote This constructor is public since JDK 1.4 113: * @since 1.1 114: */ 115: public Socket() 116: { 117: if (factory != null) 118: impl = factory.createSocketImpl(); 119: else 120: impl = new PlainSocketImpl(); 121: } 122: 123: /** 124: * Initializes a new instance of <code>Socket</code> object without 125: * connecting to a remote host. This is useful for subclasses of socket 126: * that might want this behavior. 127: * <p> 128: * Additionally, this socket will be created using the supplied 129: * implementation class instead the default class or one returned by a 130: * factory. If this value is <code>null</code>, the default Socket 131: * implementation is used. 132: * 133: * @param impl The <code>SocketImpl</code> to use for this 134: * <code>Socket</code> 135: * 136: * @exception SocketException If an error occurs 137: * 138: * @since 1.1 139: */ 140: protected Socket(SocketImpl impl) throws SocketException 141: { 142: if (impl == null) 143: this.impl = new PlainSocketImpl(); 144: else 145: this.impl = impl; 146: } 147: 148: /** 149: * Initializes a new instance of <code>Socket</code> and connects to the 150: * hostname and port specified as arguments. 151: * 152: * @param host The name of the host to connect to 153: * @param port The port number to connect to 154: * 155: * @exception UnknownHostException If the hostname cannot be resolved to a 156: * network address. 157: * @exception IOException If an error occurs 158: * @exception SecurityException If a security manager exists and its 159: * checkConnect method doesn't allow the operation 160: */ 161: public Socket(String host, int port) 162: throws UnknownHostException, IOException 163: { 164: this(InetAddress.getByName(host), port, null, 0, true); 165: } 166: 167: /** 168: * Initializes a new instance of <code>Socket</code> and connects to the 169: * address and port number specified as arguments. 170: * 171: * @param address The address to connect to 172: * @param port The port number to connect to 173: * 174: * @exception IOException If an error occurs 175: * @exception SecurityException If a security manager exists and its 176: * checkConnect method doesn't allow the operation 177: */ 178: public Socket(InetAddress address, int port) throws IOException 179: { 180: this(address, port, null, 0, true); 181: } 182: 183: /** 184: * Initializes a new instance of <code>Socket</code> that connects to the 185: * named host on the specified port and binds to the specified local address 186: * and port. 187: * 188: * @param host The name of the remote host to connect to. 189: * @param port The remote port to connect to. 190: * @param localAddr The local address to bind to. 191: * @param localPort The local port to bind to. 192: * 193: * @exception SecurityException If the <code>SecurityManager</code> 194: * exists and does not allow a connection to the specified host/port or 195: * binding to the specified local host/port. 196: * @exception IOException If a connection error occurs. 197: * 198: * @since 1.1 199: */ 200: public Socket(String host, int port, InetAddress localAddr, int localPort) 201: throws IOException 202: { 203: this(InetAddress.getByName(host), port, localAddr, localPort, true); 204: } 205: 206: /** 207: * Initializes a new instance of <code>Socket</code> and connects to the 208: * address and port number specified as arguments, plus binds to the 209: * specified local address and port. 210: * 211: * @param address The remote address to connect to 212: * @param port The remote port to connect to 213: * @param localAddr The local address to connect to 214: * @param localPort The local port to connect to 215: * 216: * @exception IOException If an error occurs 217: * @exception SecurityException If a security manager exists and its 218: * checkConnect method doesn't allow the operation 219: * 220: * @since 1.1 221: */ 222: public Socket(InetAddress address, int port, InetAddress localAddr, 223: int localPort) throws IOException 224: { 225: this(address, port, localAddr, localPort, true); 226: } 227: 228: /** 229: * Initializes a new instance of <code>Socket</code> and connects to the 230: * hostname and port specified as arguments. If the stream argument is set 231: * to <code>true</code>, then a stream socket is created. If it is 232: * <code>false</code>, a datagram socket is created. 233: * 234: * @param host The name of the host to connect to 235: * @param port The port to connect to 236: * @param stream <code>true</code> for a stream socket, <code>false</code> 237: * for a datagram socket 238: * 239: * @exception IOException If an error occurs 240: * @exception SecurityException If a security manager exists and its 241: * checkConnect method doesn't allow the operation 242: * 243: * @deprecated Use the <code>DatagramSocket</code> class to create 244: * datagram oriented sockets. 245: */ 246: public Socket(String host, int port, boolean stream) 247: throws IOException 248: { 249: this(InetAddress.getByName(host), port, null, 0, stream); 250: } 251: 252: /** 253: * Initializes a new instance of <code>Socket</code> and connects to the 254: * address and port number specified as arguments. If the stream param is 255: * <code>true</code>, a stream socket will be created, otherwise a datagram 256: * socket is created. 257: * 258: * @param host The address to connect to 259: * @param port The port number to connect to 260: * @param stream <code>true</code> to create a stream socket, 261: * <code>false</code> to create a datagram socket. 262: * 263: * @exception IOException If an error occurs 264: * @exception SecurityException If a security manager exists and its 265: * checkConnect method doesn't allow the operation 266: * 267: * @deprecated Use the <code>DatagramSocket</code> class to create 268: * datagram oriented sockets. 269: */ 270: public Socket(InetAddress host, int port, boolean stream) 271: throws IOException 272: { 273: this(host, port, null, 0, stream); 274: } 275: 276: /** 277: * This constructor is where the real work takes place. Connect to the 278: * specified address and port. Use default local values if not specified, 279: * otherwise use the local host and port passed in. Create as stream or 280: * datagram based on "stream" argument. 281: * <p> 282: * 283: * @param raddr The remote address to connect to 284: * @param rport The remote port to connect to 285: * @param laddr The local address to connect to 286: * @param lport The local port to connect to 287: * @param stream true for a stream socket, false for a datagram socket 288: * 289: * @exception IOException If an error occurs 290: * @exception SecurityException If a security manager exists and its 291: * checkConnect method doesn't allow the operation 292: */ 293: private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport, 294: boolean stream) throws IOException 295: { 296: this(); 297: 298: SecurityManager sm = System.getSecurityManager(); 299: if (sm != null) 300: sm.checkConnect(raddr.getHostAddress(), rport); 301: 302: // bind socket 303: SocketAddress bindaddr = 304: laddr == null ? null : new InetSocketAddress(laddr, lport); 305: bind(bindaddr); 306: 307: // Connect socket in case of Exceptions we must close the socket 308: // because an exception in the constructor means that the caller will 309: // not have a reference to this instance. 310: // Note: You may have the idea that the exception treatment 311: // should be moved into connect() but there is a Mauve test which 312: // shows that a failed connect should not close the socket. 313: try 314: { 315: connect(new InetSocketAddress(raddr, rport)); 316: } 317: catch (IOException ioe) 318: { 319: impl.close(); 320: throw ioe; 321: } 322: catch (RuntimeException re) 323: { 324: impl.close(); 325: throw re; 326: } 327: 328: // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port, 329: // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as 330: // that default. JDK 1.2 doc infers not to do a bind. 331: } 332: 333: private SocketImpl getImpl() throws SocketException 334: { 335: if (! implCreated) 336: { 337: try 338: { 339: impl.create(true); 340: } 341: catch (IOException x) 342: { 343: throw (SocketException) new SocketException().initCause(x); 344: } 345: implCreated = true; 346: } 347: return impl; 348: } 349: 350: /** 351: * Binds the socket to the given local address/port 352: * 353: * @param bindpoint The address/port to bind to 354: * 355: * @exception IOException If an error occurs 356: * @exception SecurityException If a security manager exists and its 357: * checkConnect method doesn't allow the operation 358: * @exception IllegalArgumentException If the address type is not supported 359: * 360: * @since 1.4 361: */ 362: public void bind(SocketAddress bindpoint) throws IOException 363: { 364: if (isClosed()) 365: throw new SocketException("socket is closed"); 366: 367: // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the 368: // socket will be bound to an ephemeral port and a valid local address. 369: if (bindpoint == null) 370: bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0); 371: 372: if (! (bindpoint instanceof InetSocketAddress)) 373: throw new IllegalArgumentException(); 374: 375: InetSocketAddress tmp = (InetSocketAddress) bindpoint; 376: 377: // bind to address/port 378: try 379: { 380: getImpl().bind(tmp.getAddress(), tmp.getPort()); 381: bound = true; 382: } 383: catch (IOException exception) 384: { 385: close(); 386: throw exception; 387: } 388: catch (RuntimeException exception) 389: { 390: close(); 391: throw exception; 392: } 393: catch (Error error) 394: { 395: close(); 396: throw error; 397: } 398: } 399: 400: /** 401: * Connects the socket with a remote address. 402: * 403: * @param endpoint The address to connect to 404: * 405: * @exception IOException If an error occurs 406: * @exception IllegalArgumentException If the addess type is not supported 407: * @exception IllegalBlockingModeException If this socket has an associated 408: * channel, and the channel is in non-blocking mode 409: * 410: * @since 1.4 411: */ 412: public void connect(SocketAddress endpoint) throws IOException 413: { 414: connect(endpoint, 0); 415: } 416: 417: /** 418: * Connects the socket with a remote address. A timeout of zero is 419: * interpreted as an infinite timeout. The connection will then block 420: * until established or an error occurs. 421: * 422: * @param endpoint The address to connect to 423: * @param timeout The length of the timeout in milliseconds, or 424: * 0 to indicate no timeout. 425: * 426: * @exception IOException If an error occurs 427: * @exception IllegalArgumentException If the address type is not supported 428: * @exception IllegalBlockingModeException If this socket has an associated 429: * channel, and the channel is in non-blocking mode 430: * @exception SocketTimeoutException If the timeout is reached 431: * @throws SecurityException if the SocketAddress is an {@link InetSocketAddress} 432: * and a security manager is present which does not 433: * allow connections on the given host and port. 434: * @since 1.4 435: */ 436: public void connect(SocketAddress endpoint, int timeout) 437: throws IOException 438: { 439: if (isClosed()) 440: throw new SocketException("socket is closed"); 441: 442: if (! (endpoint instanceof InetSocketAddress)) 443: throw new IllegalArgumentException("unsupported address type"); 444: 445: SecurityManager sm = System.getSecurityManager(); 446: if (sm != null) 447: { 448: InetSocketAddress inetAddr = (InetSocketAddress) endpoint; 449: sm.checkConnect(inetAddr.getHostName(), inetAddr.getPort()); 450: } 451: 452: // The Sun spec says that if we have an associated channel and 453: // it is in non-blocking mode, we throw an IllegalBlockingModeException. 454: // However, in our implementation if the channel itself initiated this 455: // operation, then we must honor it regardless of its blocking mode. 456: if (getChannel() != null && ! getChannel().isBlocking() 457: && ! ((PlainSocketImpl) getImpl()).isInChannelOperation()) 458: throw new IllegalBlockingModeException(); 459: 460: if (! isBound()) 461: bind(null); 462: 463: getImpl().connect(endpoint, timeout); 464: } 465: 466: /** 467: * Returns the address of the remote end of the socket. If this socket 468: * is not connected, then <code>null</code> is returned. 469: * 470: * @return The remote address this socket is connected to 471: */ 472: public InetAddress getInetAddress() 473: { 474: if (! isConnected()) 475: return null; 476: 477: try 478: { 479: return getImpl().getInetAddress(); 480: } 481: catch (SocketException e) 482: { 483: // This cannot happen as we are connected. 484: } 485: 486: return null; 487: } 488: 489: /** 490: * Returns the local address to which this socket is bound. If this socket 491: * is not connected, then a wildcard address, for which 492: * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned. 493: * 494: * @return The local address 495: * 496: * @since 1.1 497: */ 498: public InetAddress getLocalAddress() 499: { 500: if (! isBound()) 501: return InetAddress.ANY_IF; 502: 503: InetAddress addr = null; 504: 505: if (impl instanceof PlainSocketImpl) 506: addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress(); 507: 508: if (addr == null) 509: { 510: try 511: { 512: addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 513: } 514: catch (SocketException e) 515: { 516: // (hopefully) shouldn't happen 517: // throw new java.lang.InternalError 518: // ("Error in PlainSocketImpl.getOption"); 519: return null; 520: } 521: } 522: 523: // FIXME: According to libgcj, checkConnect() is supposed to be called 524: // before performing this operation. Problems: 1) We don't have the 525: // addr until after we do it, so we do a post check. 2). The docs I 526: // see don't require this in the Socket case, only DatagramSocket, but 527: // we'll assume they mean both. 528: SecurityManager sm = System.getSecurityManager(); 529: if (sm != null) 530: sm.checkConnect(addr.getHostName(), getLocalPort()); 531: 532: return addr; 533: } 534: 535: /** 536: * Returns the port number of the remote end of the socket connection. If 537: * this socket is not connected, then 0 is returned. 538: * 539: * @return The remote port this socket is connected to 540: */ 541: public int getPort() 542: { 543: if (! isConnected()) 544: return 0; 545: 546: try 547: { 548: return getImpl().getPort(); 549: } 550: catch (SocketException e) 551: { 552: // This cannot happen as we are connected. 553: } 554: 555: return 0; 556: } 557: 558: /** 559: * Returns the local port number to which this socket is bound. If this 560: * socket is not connected, then -1 is returned. 561: * 562: * @return The local port 563: */ 564: public int getLocalPort() 565: { 566: if (! isBound()) 567: return -1; 568: 569: try 570: { 571: if (getImpl() != null) 572: return getImpl().getLocalPort(); 573: } 574: catch (SocketException e) 575: { 576: // This cannot happen as we are bound. 577: } 578: 579: return -1; 580: } 581: 582: /** 583: * Returns local socket address. 584: * 585: * @return the local socket address, null if not bound 586: * 587: * @since 1.4 588: */ 589: public SocketAddress getLocalSocketAddress() 590: { 591: if (! isBound()) 592: return null; 593: 594: InetAddress addr = getLocalAddress(); 595: 596: try 597: { 598: return new InetSocketAddress(addr, getImpl().getLocalPort()); 599: } 600: catch (SocketException e) 601: { 602: // This cannot happen as we are bound. 603: return null; 604: } 605: } 606: 607: /** 608: * Returns the remote socket address. 609: * 610: * @return the remote socket address, null of not connected 611: * 612: * @since 1.4 613: */ 614: public SocketAddress getRemoteSocketAddress() 615: { 616: if (! isConnected()) 617: return null; 618: 619: try 620: { 621: return new InetSocketAddress(getImpl().getInetAddress(), 622: getImpl().getPort()); 623: } 624: catch (SocketException e) 625: { 626: // This cannot happen as we are connected. 627: return null; 628: } 629: } 630: 631: /** 632: * Returns an InputStream for reading from this socket. 633: * 634: * @return The InputStream object 635: * 636: * @exception IOException If an error occurs or Socket is not connected 637: */ 638: public InputStream getInputStream() throws IOException 639: { 640: if (isClosed()) 641: throw new SocketException("socket is closed"); 642: 643: if (! isConnected()) 644: throw new IOException("not connected"); 645: 646: return getImpl().getInputStream(); 647: } 648: 649: /** 650: * Returns an OutputStream for writing to this socket. 651: * 652: * @return The OutputStream object 653: * 654: * @exception IOException If an error occurs or Socket is not connected 655: */ 656: public OutputStream getOutputStream() throws IOException 657: { 658: if (isClosed()) 659: throw new SocketException("socket is closed"); 660: 661: if (! isConnected()) 662: throw new IOException("not connected"); 663: 664: return getImpl().getOutputStream(); 665: } 666: 667: /** 668: * Sets the TCP_NODELAY option on the socket. 669: * 670: * @param on true to enable, false to disable 671: * 672: * @exception SocketException If an error occurs or Socket is not connected 673: * 674: * @since 1.1 675: */ 676: public void setTcpNoDelay(boolean on) throws SocketException 677: { 678: if (isClosed()) 679: throw new SocketException("socket is closed"); 680: 681: getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); 682: } 683: 684: /** 685: * Tests whether or not the TCP_NODELAY option is set on the socket. 686: * Returns true if enabled, false if disabled. When on it disables the 687: * Nagle algorithm which means that packets are always send immediatly and 688: * never merged together to reduce network trafic. 689: * 690: * @return Whether or not TCP_NODELAY is set 691: * 692: * @exception SocketException If an error occurs or Socket not connected 693: * 694: * @since 1.1 695: */ 696: public boolean getTcpNoDelay() throws SocketException 697: { 698: if (isClosed()) 699: throw new SocketException("socket is closed"); 700: 701: Object on = getImpl().getOption(SocketOptions.TCP_NODELAY); 702: 703: if (on instanceof Boolean) 704: return (((Boolean) on).booleanValue()); 705: else 706: throw new SocketException("Internal Error"); 707: } 708: 709: /** 710: * Sets the value of the SO_LINGER option on the socket. If the 711: * SO_LINGER option is set on a socket and there is still data waiting to 712: * be sent when the socket is closed, then the close operation will block 713: * until either that data is delivered or until the timeout period 714: * expires. The linger interval is specified in hundreths of a second 715: * (platform specific?) 716: * 717: * @param on true to enable SO_LINGER, false to disable 718: * @param linger The SO_LINGER timeout in hundreths of a second or -1 if 719: * SO_LINGER not set. 720: * 721: * @exception SocketException If an error occurs or Socket not connected 722: * @exception IllegalArgumentException If linger is negative 723: * 724: * @since 1.1 725: */ 726: public void setSoLinger(boolean on, int linger) throws SocketException 727: { 728: if (isClosed()) 729: throw new SocketException("socket is closed"); 730: 731: if (on) 732: { 733: if (linger < 0) 734: throw new IllegalArgumentException("SO_LINGER must be >= 0"); 735: 736: if (linger > 65535) 737: linger = 65535; 738: 739: getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger)); 740: } 741: else 742: getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1)); 743: } 744: 745: /** 746: * Returns the value of the SO_LINGER option on the socket. If the 747: * SO_LINGER option is set on a socket and there is still data waiting to 748: * be sent when the socket is closed, then the close operation will block 749: * until either that data is delivered or until the timeout period 750: * expires. This method either returns the timeouts (in hundredths of 751: * of a second (platform specific?)) if SO_LINGER is set, or -1 if 752: * SO_LINGER is not set. 753: * 754: * @return The SO_LINGER timeout in hundreths of a second or -1 755: * if SO_LINGER not set 756: * 757: * @exception SocketException If an error occurs or Socket is not connected 758: * 759: * @since 1.1 760: */ 761: public int getSoLinger() throws SocketException 762: { 763: if (isClosed()) 764: throw new SocketException("socket is closed"); 765: 766: Object linger = getImpl().getOption(SocketOptions.SO_LINGER); 767: 768: if (linger instanceof Integer) 769: return (((Integer) linger).intValue()); 770: else 771: return -1; 772: } 773: 774: /** 775: * Sends urgent data through the socket 776: * 777: * @param data The data to send. 778: * Only the lowest eight bits of data are sent 779: * 780: * @exception IOException If an error occurs 781: * 782: * @since 1.4 783: */ 784: public void sendUrgentData(int data) throws IOException 785: { 786: if (isClosed()) 787: throw new SocketException("socket is closed"); 788: 789: getImpl().sendUrgentData(data); 790: } 791: 792: /** 793: * Enables/disables the SO_OOBINLINE option 794: * 795: * @param on True if SO_OOBLINE should be enabled 796: * 797: * @exception SocketException If an error occurs 798: * 799: * @since 1.4 800: */ 801: public void setOOBInline(boolean on) throws SocketException 802: { 803: if (isClosed()) 804: throw new SocketException("socket is closed"); 805: 806: getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on)); 807: } 808: 809: /** 810: * Returns the current setting of the SO_OOBINLINE option for this socket 811: * 812: * @return True if SO_OOBINLINE is set, false otherwise. 813: * 814: * @exception SocketException If an error occurs 815: * 816: * @since 1.4 817: */ 818: public boolean getOOBInline() throws SocketException 819: { 820: if (isClosed()) 821: throw new SocketException("socket is closed"); 822: 823: Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE); 824: 825: if (buf instanceof Boolean) 826: return (((Boolean) buf).booleanValue()); 827: else 828: throw new SocketException("Internal Error: Unexpected type"); 829: } 830: 831: /** 832: * Sets the value of the SO_TIMEOUT option on the socket. If this value 833: * is set, and an read/write is performed that does not complete within 834: * the timeout period, a short count is returned (or an EWOULDBLOCK signal 835: * would be sent in Unix if no data had been read). A value of 0 for 836: * this option implies that there is no timeout (ie, operations will 837: * block forever). On systems that have separate read and write timeout 838: * values, this method returns the read timeout. This 839: * value is in milliseconds. 840: * 841: * @param timeout The length of the timeout in milliseconds, or 842: * 0 to indicate no timeout. 843: * 844: * @exception SocketException If an error occurs or Socket not connected 845: * 846: * @since 1.1 847: */ 848: public synchronized void setSoTimeout(int timeout) throws SocketException 849: { 850: if (isClosed()) 851: throw new SocketException("socket is closed"); 852: 853: if (timeout < 0) 854: throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); 855: 856: getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 857: } 858: 859: /** 860: * Returns the value of the SO_TIMEOUT option on the socket. If this value 861: * is set, and an read/write is performed that does not complete within 862: * the timeout period, a short count is returned (or an EWOULDBLOCK signal 863: * would be sent in Unix if no data had been read). A value of 0 for 864: * this option implies that there is no timeout (ie, operations will 865: * block forever). On systems that have separate read and write timeout 866: * values, this method returns the read timeout. This 867: * value is in thousandths of a second (implementation specific?). 868: * 869: * @return The length of the timeout in thousandth's of a second or 0 870: * if not set 871: * 872: * @exception SocketException If an error occurs or Socket not connected 873: * 874: * @since 1.1 875: */ 876: public synchronized int getSoTimeout() throws SocketException 877: { 878: if (isClosed()) 879: throw new SocketException("socket is closed"); 880: 881: Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT); 882: if (timeout instanceof Integer) 883: return (((Integer) timeout).intValue()); 884: else 885: return 0; 886: } 887: 888: /** 889: * This method sets the value for the system level socket option 890: * SO_SNDBUF to the specified value. Note that valid values for this 891: * option are specific to a given operating system. 892: * 893: * @param size The new send buffer size. 894: * 895: * @exception SocketException If an error occurs or Socket not connected 896: * @exception IllegalArgumentException If size is 0 or negative 897: * 898: * @since 1.2 899: */ 900: public void setSendBufferSize(int size) throws SocketException 901: { 902: if (isClosed()) 903: throw new SocketException("socket is closed"); 904: 905: if (size <= 0) 906: throw new IllegalArgumentException("SO_SNDBUF value must be > 0"); 907: 908: getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 909: } 910: 911: /** 912: * This method returns the value of the system level socket option 913: * SO_SNDBUF, which is used by the operating system to tune buffer 914: * sizes for data transfers. 915: * 916: * @return The send buffer size. 917: * 918: * @exception SocketException If an error occurs or socket not connected 919: * 920: * @since 1.2 921: */ 922: public int getSendBufferSize() throws SocketException 923: { 924: if (isClosed()) 925: throw new SocketException("socket is closed"); 926: 927: Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); 928: 929: if (buf instanceof Integer) 930: return (((Integer) buf).intValue()); 931: else 932: throw new SocketException("Internal Error: Unexpected type"); 933: } 934: 935: /** 936: * This method sets the value for the system level socket option 937: * SO_RCVBUF to the specified value. Note that valid values for this 938: * option are specific to a given operating system. 939: * 940: * @param size The new receive buffer size. 941: * 942: * @exception SocketException If an error occurs or Socket is not connected 943: * @exception IllegalArgumentException If size is 0 or negative 944: * 945: * @since 1.2 946: */ 947: public void setReceiveBufferSize(int size) throws SocketException 948: { 949: if (isClosed()) 950: throw new SocketException("socket is closed"); 951: 952: if (size <= 0) 953: throw new IllegalArgumentException("SO_RCVBUF value must be > 0"); 954: 955: getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 956: } 957: 958: /** 959: * This method returns the value of the system level socket option 960: * SO_RCVBUF, which is used by the operating system to tune buffer 961: * sizes for data transfers. 962: * 963: * @return The receive buffer size. 964: * 965: * @exception SocketException If an error occurs or Socket is not connected 966: * 967: * @since 1.2 968: */ 969: public int getReceiveBufferSize() throws SocketException 970: { 971: if (isClosed()) 972: throw new SocketException("socket is closed"); 973: 974: Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); 975: 976: if (buf instanceof Integer) 977: return (((Integer) buf).intValue()); 978: else 979: throw new SocketException("Internal Error: Unexpected type"); 980: } 981: 982: /** 983: * This method sets the value for the socket level socket option 984: * SO_KEEPALIVE. 985: * 986: * @param on True if SO_KEEPALIVE should be enabled 987: * 988: * @exception SocketException If an error occurs or Socket is not connected 989: * 990: * @since 1.3 991: */ 992: public void setKeepAlive(boolean on) throws SocketException 993: { 994: if (isClosed()) 995: throw new SocketException("socket is closed"); 996: 997: getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on)); 998: } 999: 1000: /** 1001: * This method returns the value of the socket level socket option 1002: * SO_KEEPALIVE. 1003: * 1004: * @return The setting 1005: * 1006: * @exception SocketException If an error occurs or Socket is not connected 1007: * 1008: * @since 1.3 1009: */ 1010: public boolean getKeepAlive() throws SocketException 1011: { 1012: if (isClosed()) 1013: throw new SocketException("socket is closed"); 1014: 1015: Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE); 1016: 1017: if (buf instanceof Boolean) 1018: return (((Boolean) buf).booleanValue()); 1019: else 1020: throw new SocketException("Internal Error: Unexpected type"); 1021: } 1022: 1023: /** 1024: * Closes the socket. 1025: * 1026: * @exception IOException If an error occurs 1027: */ 1028: public synchronized void close() throws IOException 1029: { 1030: if (isClosed()) 1031: return; 1032: 1033: impl.close(); 1034: impl = null; 1035: } 1036: 1037: /** 1038: * Converts this <code>Socket</code> to a <code>String</code>. 1039: * 1040: * @return The <code>String</code> representation of this <code>Socket</code> 1041: */ 1042: public String toString() 1043: { 1044: try 1045: { 1046: if (isConnected()) 1047: return (super.toString() 1048: + " [addr=" + getImpl().getInetAddress() + ",port=" 1049: + getImpl().getPort() + ",localport=" 1050: + getImpl().getLocalPort() + "]"); 1051: } 1052: catch (SocketException e) 1053: { 1054: // This cannot happen as we are connected. 1055: } 1056: 1057: return super.toString() + " [unconnected]"; 1058: } 1059: 1060: /** 1061: * Sets the <code>SocketImplFactory</code>. This may be done only once per 1062: * virtual machine. Subsequent attempts will generate a 1063: * <code>SocketException</code>. Note that a <code>SecurityManager</code> 1064: * check is made prior to setting the factory. If 1065: * insufficient privileges exist to set the factory, then an 1066: * <code>IOException</code> will be thrown. 1067: * 1068: * @param fac the factory to set 1069: * 1070: * @exception SecurityException If the <code>SecurityManager</code> does 1071: * not allow this operation. 1072: * @exception SocketException If the SocketImplFactory is already defined 1073: * @exception IOException If any other error occurs 1074: */ 1075: public static synchronized void setSocketImplFactory(SocketImplFactory fac) 1076: throws IOException 1077: { 1078: // See if already set 1079: if (factory != null) 1080: throw new SocketException("SocketImplFactory already defined"); 1081: 1082: // Check permissions 1083: SecurityManager sm = System.getSecurityManager(); 1084: if (sm != null) 1085: sm.checkSetFactory(); 1086: 1087: if (fac == null) 1088: throw new SocketException("SocketImplFactory cannot be null"); 1089: 1090: factory = fac; 1091: } 1092: 1093: /** 1094: * Closes the input side of the socket stream. 1095: * 1096: * @exception IOException If an error occurs. 1097: * 1098: * @since 1.3 1099: */ 1100: public void shutdownInput() throws IOException 1101: { 1102: if (isClosed()) 1103: throw new SocketException("socket is closed"); 1104: 1105: getImpl().shutdownInput(); 1106: inputShutdown = true; 1107: } 1108: 1109: /** 1110: * Closes the output side of the socket stream. 1111: * 1112: * @exception IOException If an error occurs. 1113: * 1114: * @since 1.3 1115: */ 1116: public void shutdownOutput() throws IOException 1117: { 1118: if (isClosed()) 1119: throw new SocketException("socket is closed"); 1120: 1121: getImpl().shutdownOutput(); 1122: outputShutdown = true; 1123: } 1124: 1125: /** 1126: * Returns the socket channel associated with this socket. 1127: * 1128: * @return the associated socket channel, 1129: * null if no associated channel exists 1130: * 1131: * @since 1.4 1132: */ 1133: public SocketChannel getChannel() 1134: { 1135: return null; 1136: } 1137: 1138: /** 1139: * Checks if the SO_REUSEADDR option is enabled 1140: * 1141: * @return True if SO_REUSEADDR is set, false otherwise. 1142: * 1143: * @exception SocketException If an error occurs 1144: * 1145: * @since 1.4 1146: */ 1147: public boolean getReuseAddress() throws SocketException 1148: { 1149: if (isClosed()) 1150: throw new SocketException("socket is closed"); 1151: 1152: Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR); 1153: 1154: if (! (reuseaddr instanceof Boolean)) 1155: throw new SocketException("Internal Error"); 1156: 1157: return ((Boolean) reuseaddr).booleanValue(); 1158: } 1159: 1160: /** 1161: * Enables/Disables the SO_REUSEADDR option 1162: * 1163: * @param reuseAddress true if SO_REUSEADDR should be enabled, 1164: * false otherwise 1165: * 1166: * @exception SocketException If an error occurs 1167: * 1168: * @since 1.4 1169: */ 1170: public void setReuseAddress(boolean reuseAddress) throws SocketException 1171: { 1172: if (isClosed()) 1173: throw new SocketException("socket is closed"); 1174: 1175: getImpl().setOption(SocketOptions.SO_REUSEADDR, 1176: Boolean.valueOf(reuseAddress)); 1177: } 1178: 1179: /** 1180: * Returns the current traffic class 1181: * 1182: * @return The current traffic class. 1183: * 1184: * @exception SocketException If an error occurs 1185: * 1186: * @see Socket#setTrafficClass(int tc) 1187: * 1188: * @since 1.4 1189: */ 1190: public int getTrafficClass() throws SocketException 1191: { 1192: if (isClosed()) 1193: throw new SocketException("socket is closed"); 1194: 1195: Object obj = getImpl().getOption(SocketOptions.IP_TOS); 1196: 1197: if (obj instanceof Integer) 1198: return ((Integer) obj).intValue(); 1199: else 1200: throw new SocketException("Unexpected type"); 1201: } 1202: 1203: /** 1204: * Sets the traffic class value 1205: * 1206: * @param tc The traffic class 1207: * 1208: * @exception SocketException If an error occurs 1209: * @exception IllegalArgumentException If tc value is illegal 1210: * 1211: * @see Socket#getTrafficClass() 1212: * 1213: * @since 1.4 1214: */ 1215: public void setTrafficClass(int tc) throws SocketException 1216: { 1217: if (isClosed()) 1218: throw new SocketException("socket is closed"); 1219: 1220: if (tc < 0 || tc > 255) 1221: throw new IllegalArgumentException(); 1222: 1223: getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc)); 1224: } 1225: 1226: /** 1227: * Checks if the socket is connected 1228: * 1229: * @return True if socket is connected, false otherwise. 1230: * 1231: * @since 1.4 1232: */ 1233: public boolean isConnected() 1234: { 1235: if (impl == null) 1236: return false; 1237: 1238: return impl.getInetAddress() != null; 1239: } 1240: 1241: /** 1242: * Checks if the socket is already bound. 1243: * 1244: * @return True if socket is bound, false otherwise. 1245: * 1246: * @since 1.4 1247: */ 1248: public boolean isBound() 1249: { 1250: if (isClosed()) 1251: return false; 1252: if (impl instanceof PlainSocketImpl) 1253: { 1254: InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress(); 1255: return addr != null && addr.getAddress() != null; 1256: } 1257: return bound; 1258: } 1259: 1260: /** 1261: * Checks if the socket is closed. 1262: * 1263: * @return True if socket is closed, false otherwise. 1264: * 1265: * @since 1.4 1266: */ 1267: public boolean isClosed() 1268: { 1269: SocketChannel channel = getChannel(); 1270: 1271: return impl == null || (channel != null && ! channel.isOpen()); 1272: } 1273: 1274: /** 1275: * Checks if the socket's input stream is shutdown 1276: * 1277: * @return True if input is shut down. 1278: * 1279: * @since 1.4 1280: */ 1281: public boolean isInputShutdown() 1282: { 1283: return inputShutdown; 1284: } 1285: 1286: /** 1287: * Checks if the socket's output stream is shutdown 1288: * 1289: * @return True if output is shut down. 1290: * 1291: * @since 1.4 1292: */ 1293: public boolean isOutputShutdown() 1294: { 1295: return outputShutdown; 1296: } 1297: }