| GNU Classpath (0.95) | |
| 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: * 432: * @since 1.4 433: */ 434: public void connect(SocketAddress endpoint, int timeout) 435: throws IOException 436: { 437: if (isClosed()) 438: throw new SocketException("socket is closed"); 439: 440: if (! (endpoint instanceof InetSocketAddress)) 441: throw new IllegalArgumentException("unsupported address type"); 442: 443: // The Sun spec says that if we have an associated channel and 444: // it is in non-blocking mode, we throw an IllegalBlockingModeException. 445: // However, in our implementation if the channel itself initiated this 446: // operation, then we must honor it regardless of its blocking mode. 447: if (getChannel() != null && ! getChannel().isBlocking() 448: && ! ((PlainSocketImpl) getImpl()).isInChannelOperation()) 449: throw new IllegalBlockingModeException(); 450: 451: if (! isBound()) 452: bind(null); 453: 454: getImpl().connect(endpoint, timeout); 455: } 456: 457: /** 458: * Returns the address of the remote end of the socket. If this socket 459: * is not connected, then <code>null</code> is returned. 460: * 461: * @return The remote address this socket is connected to 462: */ 463: public InetAddress getInetAddress() 464: { 465: if (! isConnected()) 466: return null; 467: 468: try 469: { 470: return getImpl().getInetAddress(); 471: } 472: catch (SocketException e) 473: { 474: // This cannot happen as we are connected. 475: } 476: 477: return null; 478: } 479: 480: /** 481: * Returns the local address to which this socket is bound. If this socket 482: * is not connected, then a wildcard address, for which 483: * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned. 484: * 485: * @return The local address 486: * 487: * @since 1.1 488: */ 489: public InetAddress getLocalAddress() 490: { 491: if (! isBound()) 492: return InetAddress.ANY_IF; 493: 494: InetAddress addr = null; 495: 496: if (impl instanceof PlainSocketImpl) 497: addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress(); 498: 499: if (addr == null) 500: { 501: try 502: { 503: addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 504: } 505: catch (SocketException e) 506: { 507: // (hopefully) shouldn't happen 508: // throw new java.lang.InternalError 509: // ("Error in PlainSocketImpl.getOption"); 510: return null; 511: } 512: } 513: 514: // FIXME: According to libgcj, checkConnect() is supposed to be called 515: // before performing this operation. Problems: 1) We don't have the 516: // addr until after we do it, so we do a post check. 2). The docs I 517: // see don't require this in the Socket case, only DatagramSocket, but 518: // we'll assume they mean both. 519: SecurityManager sm = System.getSecurityManager(); 520: if (sm != null) 521: sm.checkConnect(addr.getHostName(), getLocalPort()); 522: 523: return addr; 524: } 525: 526: /** 527: * Returns the port number of the remote end of the socket connection. If 528: * this socket is not connected, then 0 is returned. 529: * 530: * @return The remote port this socket is connected to 531: */ 532: public int getPort() 533: { 534: if (! isConnected()) 535: return 0; 536: 537: try 538: { 539: return getImpl().getPort(); 540: } 541: catch (SocketException e) 542: { 543: // This cannot happen as we are connected. 544: } 545: 546: return 0; 547: } 548: 549: /** 550: * Returns the local port number to which this socket is bound. If this 551: * socket is not connected, then -1 is returned. 552: * 553: * @return The local port 554: */ 555: public int getLocalPort() 556: { 557: if (! isBound()) 558: return -1; 559: 560: try 561: { 562: if (getImpl() != null) 563: return getImpl().getLocalPort(); 564: } 565: catch (SocketException e) 566: { 567: // This cannot happen as we are bound. 568: } 569: 570: return -1; 571: } 572: 573: /** 574: * Returns local socket address. 575: * 576: * @return the local socket address, null if not bound 577: * 578: * @since 1.4 579: */ 580: public SocketAddress getLocalSocketAddress() 581: { 582: if (! isBound()) 583: return null; 584: 585: InetAddress addr = getLocalAddress(); 586: 587: try 588: { 589: return new InetSocketAddress(addr, getImpl().getLocalPort()); 590: } 591: catch (SocketException e) 592: { 593: // This cannot happen as we are bound. 594: return null; 595: } 596: } 597: 598: /** 599: * Returns the remote socket address. 600: * 601: * @return the remote socket address, null of not connected 602: * 603: * @since 1.4 604: */ 605: public SocketAddress getRemoteSocketAddress() 606: { 607: if (! isConnected()) 608: return null; 609: 610: try 611: { 612: return new InetSocketAddress(getImpl().getInetAddress(), 613: getImpl().getPort()); 614: } 615: catch (SocketException e) 616: { 617: // This cannot happen as we are connected. 618: return null; 619: } 620: } 621: 622: /** 623: * Returns an InputStream for reading from this socket. 624: * 625: * @return The InputStream object 626: * 627: * @exception IOException If an error occurs or Socket is not connected 628: */ 629: public InputStream getInputStream() throws IOException 630: { 631: if (isClosed()) 632: throw new SocketException("socket is closed"); 633: 634: if (! isConnected()) 635: throw new IOException("not connected"); 636: 637: return getImpl().getInputStream(); 638: } 639: 640: /** 641: * Returns an OutputStream for writing to this socket. 642: * 643: * @return The OutputStream object 644: * 645: * @exception IOException If an error occurs or Socket is not connected 646: */ 647: public OutputStream getOutputStream() throws IOException 648: { 649: if (isClosed()) 650: throw new SocketException("socket is closed"); 651: 652: if (! isConnected()) 653: throw new IOException("not connected"); 654: 655: return getImpl().getOutputStream(); 656: } 657: 658: /** 659: * Sets the TCP_NODELAY option on the socket. 660: * 661: * @param on true to enable, false to disable 662: * 663: * @exception SocketException If an error occurs or Socket is not connected 664: * 665: * @since 1.1 666: */ 667: public void setTcpNoDelay(boolean on) throws SocketException 668: { 669: if (isClosed()) 670: throw new SocketException("socket is closed"); 671: 672: getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); 673: } 674: 675: /** 676: * Tests whether or not the TCP_NODELAY option is set on the socket. 677: * Returns true if enabled, false if disabled. When on it disables the 678: * Nagle algorithm which means that packets are always send immediatly and 679: * never merged together to reduce network trafic. 680: * 681: * @return Whether or not TCP_NODELAY is set 682: * 683: * @exception SocketException If an error occurs or Socket not connected 684: * 685: * @since 1.1 686: */ 687: public boolean getTcpNoDelay() throws SocketException 688: { 689: if (isClosed()) 690: throw new SocketException("socket is closed"); 691: 692: Object on = getImpl().getOption(SocketOptions.TCP_NODELAY); 693: 694: if (on instanceof Boolean) 695: return (((Boolean) on).booleanValue()); 696: else 697: throw new SocketException("Internal Error"); 698: } 699: 700: /** 701: * Sets the value of the SO_LINGER option on the socket. If the 702: * SO_LINGER option is set on a socket and there is still data waiting to 703: * be sent when the socket is closed, then the close operation will block 704: * until either that data is delivered or until the timeout period 705: * expires. The linger interval is specified in hundreths of a second 706: * (platform specific?) 707: * 708: * @param on true to enable SO_LINGER, false to disable 709: * @param linger The SO_LINGER timeout in hundreths of a second or -1 if 710: * SO_LINGER not set. 711: * 712: * @exception SocketException If an error occurs or Socket not connected 713: * @exception IllegalArgumentException If linger is negative 714: * 715: * @since 1.1 716: */ 717: public void setSoLinger(boolean on, int linger) throws SocketException 718: { 719: if (isClosed()) 720: throw new SocketException("socket is closed"); 721: 722: if (on) 723: { 724: if (linger < 0) 725: throw new IllegalArgumentException("SO_LINGER must be >= 0"); 726: 727: if (linger > 65535) 728: linger = 65535; 729: 730: getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger)); 731: } 732: else 733: getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1)); 734: } 735: 736: /** 737: * Returns the value of the SO_LINGER option on the socket. If the 738: * SO_LINGER option is set on a socket and there is still data waiting to 739: * be sent when the socket is closed, then the close operation will block 740: * until either that data is delivered or until the timeout period 741: * expires. This method either returns the timeouts (in hundredths of 742: * of a second (platform specific?)) if SO_LINGER is set, or -1 if 743: * SO_LINGER is not set. 744: * 745: * @return The SO_LINGER timeout in hundreths of a second or -1 746: * if SO_LINGER not set 747: * 748: * @exception SocketException If an error occurs or Socket is not connected 749: * 750: * @since 1.1 751: */ 752: public int getSoLinger() throws SocketException 753: { 754: if (isClosed()) 755: throw new SocketException("socket is closed"); 756: 757: Object linger = getImpl().getOption(SocketOptions.SO_LINGER); 758: 759: if (linger instanceof Integer) 760: return (((Integer) linger).intValue()); 761: else 762: return -1; 763: } 764: 765: /** 766: * Sends urgent data through the socket 767: * 768: * @param data The data to send. 769: * Only the lowest eight bits of data are sent 770: * 771: * @exception IOException If an error occurs 772: * 773: * @since 1.4 774: */ 775: public void sendUrgentData(int data) throws IOException 776: { 777: if (isClosed()) 778: throw new SocketException("socket is closed"); 779: 780: getImpl().sendUrgentData(data); 781: } 782: 783: /** 784: * Enables/disables the SO_OOBINLINE option 785: * 786: * @param on True if SO_OOBLINE should be enabled 787: * 788: * @exception SocketException If an error occurs 789: * 790: * @since 1.4 791: */ 792: public void setOOBInline(boolean on) throws SocketException 793: { 794: if (isClosed()) 795: throw new SocketException("socket is closed"); 796: 797: getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on)); 798: } 799: 800: /** 801: * Returns the current setting of the SO_OOBINLINE option for this socket 802: * 803: * @return True if SO_OOBINLINE is set, false otherwise. 804: * 805: * @exception SocketException If an error occurs 806: * 807: * @since 1.4 808: */ 809: public boolean getOOBInline() throws SocketException 810: { 811: if (isClosed()) 812: throw new SocketException("socket is closed"); 813: 814: Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE); 815: 816: if (buf instanceof Boolean) 817: return (((Boolean) buf).booleanValue()); 818: else 819: throw new SocketException("Internal Error: Unexpected type"); 820: } 821: 822: /** 823: * Sets the value of the SO_TIMEOUT option on the socket. If this value 824: * is set, and an read/write is performed that does not complete within 825: * the timeout period, a short count is returned (or an EWOULDBLOCK signal 826: * would be sent in Unix if no data had been read). A value of 0 for 827: * this option implies that there is no timeout (ie, operations will 828: * block forever). On systems that have separate read and write timeout 829: * values, this method returns the read timeout. This 830: * value is in milliseconds. 831: * 832: * @param timeout The length of the timeout in milliseconds, or 833: * 0 to indicate no timeout. 834: * 835: * @exception SocketException If an error occurs or Socket not connected 836: * 837: * @since 1.1 838: */ 839: public synchronized void setSoTimeout(int timeout) throws SocketException 840: { 841: if (isClosed()) 842: throw new SocketException("socket is closed"); 843: 844: if (timeout < 0) 845: throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); 846: 847: getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout)); 848: } 849: 850: /** 851: * Returns the value of the SO_TIMEOUT option on the socket. If this value 852: * is set, and an read/write is performed that does not complete within 853: * the timeout period, a short count is returned (or an EWOULDBLOCK signal 854: * would be sent in Unix if no data had been read). A value of 0 for 855: * this option implies that there is no timeout (ie, operations will 856: * block forever). On systems that have separate read and write timeout 857: * values, this method returns the read timeout. This 858: * value is in thousandths of a second (implementation specific?). 859: * 860: * @return The length of the timeout in thousandth's of a second or 0 861: * if not set 862: * 863: * @exception SocketException If an error occurs or Socket not connected 864: * 865: * @since 1.1 866: */ 867: public synchronized int getSoTimeout() throws SocketException 868: { 869: if (isClosed()) 870: throw new SocketException("socket is closed"); 871: 872: Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT); 873: if (timeout instanceof Integer) 874: return (((Integer) timeout).intValue()); 875: else 876: return 0; 877: } 878: 879: /** 880: * This method sets the value for the system level socket option 881: * SO_SNDBUF to the specified value. Note that valid values for this 882: * option are specific to a given operating system. 883: * 884: * @param size The new send buffer size. 885: * 886: * @exception SocketException If an error occurs or Socket not connected 887: * @exception IllegalArgumentException If size is 0 or negative 888: * 889: * @since 1.2 890: */ 891: public void setSendBufferSize(int size) throws SocketException 892: { 893: if (isClosed()) 894: throw new SocketException("socket is closed"); 895: 896: if (size <= 0) 897: throw new IllegalArgumentException("SO_SNDBUF value must be > 0"); 898: 899: getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size)); 900: } 901: 902: /** 903: * This method returns the value of the system level socket option 904: * SO_SNDBUF, which is used by the operating system to tune buffer 905: * sizes for data transfers. 906: * 907: * @return The send buffer size. 908: * 909: * @exception SocketException If an error occurs or socket not connected 910: * 911: * @since 1.2 912: */ 913: public int getSendBufferSize() throws SocketException 914: { 915: if (isClosed()) 916: throw new SocketException("socket is closed"); 917: 918: Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); 919: 920: if (buf instanceof Integer) 921: return (((Integer) buf).intValue()); 922: else 923: throw new SocketException("Internal Error: Unexpected type"); 924: } 925: 926: /** 927: * This method sets the value for the system level socket option 928: * SO_RCVBUF to the specified value. Note that valid values for this 929: * option are specific to a given operating system. 930: * 931: * @param size The new receive buffer size. 932: * 933: * @exception SocketException If an error occurs or Socket is not connected 934: * @exception IllegalArgumentException If size is 0 or negative 935: * 936: * @since 1.2 937: */ 938: