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