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: public void setReceiveBufferSize(int size) throws SocketException 939: { 940: if (isClosed()) 941: throw new SocketException("socket is closed"); 942: 943: if (size <= 0) 944: throw new IllegalArgumentException("SO_RCVBUF value must be > 0"); 945: 946: getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size)); 947: } 948: 949: /** 950: * This method returns the value of the system level socket option 951: * SO_RCVBUF, which is used by the operating system to tune buffer 952: * sizes for data transfers. 953: * 954: * @return The receive buffer size. 955: * 956: * @exception SocketException If an error occurs or Socket is not connected 957: * 958: * @since 1.2 959: */ 960: public int getReceiveBufferSize() throws SocketException 961: { 962: if (isClosed()) 963: throw new SocketException("socket is closed"); 964: 965: Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); 966: 967: if (buf instanceof Integer) 968: return (((Integer) buf).intValue()); 969: else 970: throw new SocketException("Internal Error: Unexpected type"); 971: } 972: 973: /** 974: * This method sets the value for the socket level socket option 975: * SO_KEEPALIVE. 976: * 977: * @param on True if SO_KEEPALIVE should be enabled 978: * 979: * @exception SocketException If an error occurs or Socket is not connected 980: * 981: * @since 1.3 982: */ 983: public void setKeepAlive(boolean on) throws SocketException 984: { 985: if (isClosed()) 986: throw new SocketException("socket is closed"); 987: 988: getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on)); 989: } 990: 991: /** 992: * This method returns the value of the socket level socket option 993: * SO_KEEPALIVE. 994: * 995: * @return The setting 996: * 997: * @exception SocketException If an error occurs or Socket is not connected 998: * 999: * @since 1.3 1000: */ 1001: public boolean getKeepAlive() throws SocketException 1002: { 1003: if (isClosed()) 1004: throw new SocketException("socket is closed"); 1005: 1006: Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE); 1007: 1008: if (buf instanceof Boolean) 1009: return (((Boolean) buf).booleanValue()); 1010: else 1011: throw new SocketException("Internal Error: Unexpected type"); 1012: } 1013: 1014: /** 1015: * Closes the socket. 1016: * 1017: * @exception IOException If an error occurs 1018: */ 1019: public synchronized void close() throws IOException 1020: { 1021: if (isClosed()) 1022: return; 1023: 1024: impl.close(); 1025: impl = null; 1026: } 1027: 1028: /** 1029: * Converts this <code>Socket</code> to a <code>String</code>. 1030: * 1031: * @return The <code>String</code> representation of this <code>Socket</code> 1032: */ 1033: public String toString() 1034: { 1035: try 1036: { 1037: if (isConnected()) 1038: return (super.toString() 1039: + " [addr=" + getImpl().getInetAddress() + ",port=" 1040: + getImpl().getPort() + ",localport=" 1041: + getImpl().getLocalPort() + "]"); 1042: } 1043: catch (SocketException e) 1044: { 1045: // This cannot happen as we are connected. 1046: } 1047: 1048: return super.toString() + " [unconnected]"; 1049: } 1050: 1051: /** 1052: * Sets the <code>SocketImplFactory</code>. This may be done only once per 1053: * virtual machine. Subsequent attempts will generate a 1054: * <code>SocketException</code>. Note that a <code>SecurityManager</code> 1055: * check is made prior to setting the factory. If 1056: * insufficient privileges exist to set the factory, then an 1057: * <code>IOException</code> will be thrown. 1058: * 1059: * @param fac the factory to set 1060: * 1061: * @exception SecurityException If the <code>SecurityManager</code> does 1062: * not allow this operation. 1063: * @exception SocketException If the SocketImplFactory is already defined 1064: * @exception IOException If any other error occurs 1065: */ 1066: public static synchronized void setSocketImplFactory(SocketImplFactory fac) 1067: throws IOException 1068: { 1069: // See if already set 1070: if (factory != null) 1071: throw new SocketException("SocketImplFactory already defined"); 1072: 1073: // Check permissions 1074: SecurityManager sm = System.getSecurityManager(); 1075: if (sm != null) 1076: sm.checkSetFactory(); 1077: 1078: if (fac == null) 1079: throw new SocketException("SocketImplFactory cannot be null"); 1080: 1081: factory = fac; 1082: } 1083: 1084: /** 1085: * Closes the input side of the socket stream. 1086: * 1087: * @exception IOException If an error occurs. 1088: * 1089: * @since 1.3 1090: */ 1091: public void shutdownInput() throws IOException 1092: { 1093: if (isClosed()) 1094: throw new SocketException("socket is closed"); 1095: 1096: getImpl().shutdownInput(); 1097: inputShutdown = true; 1098: } 1099: 1100: /** 1101: * Closes the output side of the socket stream. 1102: * 1103: * @exception IOException If an error occurs. 1104: * 1105: * @since 1.3 1106: */ 1107: public void shutdownOutput() throws IOException 1108: { 1109: if (isClosed()) 1110: throw new SocketException("socket is closed"); 1111: 1112: getImpl().shutdownOutput(); 1113: outputShutdown = true; 1114: } 1115: 1116: /** 1117: * Returns the socket channel associated with this socket. 1118: * 1119: * @return the associated socket channel, 1120: * null if no associated channel exists 1121: * 1122: * @since 1.4 1123: */ 1124: public SocketChannel getChannel() 1125: { 1126: return null; 1127: } 1128: 1129: /** 1130: * Checks if the SO_REUSEADDR option is enabled 1131: * 1132: * @return True if SO_REUSEADDR is set, false otherwise. 1133: * 1134: * @exception SocketException If an error occurs 1135: * 1136: * @since 1.4 1137: */ 1138: public boolean getReuseAddress() throws SocketException 1139: { 1140: if (isClosed()) 1141: throw new SocketException("socket is closed"); 1142: 1143: Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR); 1144: 1145: if (! (reuseaddr instanceof Boolean)) 1146: throw new SocketException("Internal Error"); 1147: 1148: return ((Boolean) reuseaddr).booleanValue(); 1149: } 1150: 1151: /** 1152: * Enables/Disables the SO_REUSEADDR option 1153: * 1154: * @param reuseAddress true if SO_REUSEADDR should be enabled, 1155: * false otherwise 1156: * 1157: * @exception SocketException If an error occurs 1158: * 1159: * @since 1.4 1160: */ 1161: public void setReuseAddress(boolean reuseAddress) throws SocketException 1162: { 1163: if (isClosed()) 1164: throw new SocketException("socket is closed"); 1165: 1166: getImpl().setOption(SocketOptions.SO_REUSEADDR, 1167: Boolean.valueOf(reuseAddress)); 1168: } 1169: 1170: /** 1171: * Returns the current traffic class 1172: * 1173: * @return The current traffic class. 1174: * 1175: * @exception SocketException If an error occurs 1176: * 1177: * @see Socket#setTrafficClass(int tc) 1178: * 1179: * @since 1.4 1180: */ 1181: public int getTrafficClass() throws SocketException 1182: { 1183: if (isClosed()) 1184: throw new SocketException("socket is closed"); 1185: 1186: Object obj = getImpl().getOption(SocketOptions.IP_TOS); 1187: 1188: if (obj instanceof Integer) 1189: return ((Integer) obj).intValue(); 1190: else 1191: throw new SocketException("Unexpected type"); 1192: } 1193: 1194: /** 1195: * Sets the traffic class value 1196: * 1197: * @param tc The traffic class 1198: * 1199: * @exception SocketException If an error occurs 1200: * @exception IllegalArgumentException If tc value is illegal 1201: * 1202: * @see Socket#getTrafficClass() 1203: * 1204: * @since 1.4 1205: */ 1206: public void setTrafficClass(int tc) throws SocketException 1207: { 1208: if (isClosed()) 1209: throw new SocketException("socket is closed"); 1210: 1211: if (tc < 0 || tc > 255) 1212: throw new IllegalArgumentException(); 1213: 1214: getImpl().setOption(SocketOptions.IP_TOS, new Integer(tc)); 1215: } 1216: 1217: /** 1218: * Checks if the socket is connected 1219: * 1220: * @return True if socket is connected, false otherwise. 1221: * 1222: * @since 1.4 1223: */ 1224: public boolean isConnected() 1225: { 1226: if (impl == null) 1227: return false; 1228: 1229: return impl.getInetAddress() != null; 1230: } 1231: 1232: /** 1233: * Checks if the socket is already bound. 1234: * 1235: * @return True if socket is bound, false otherwise. 1236: * 1237: * @since 1.4 1238: */ 1239: public boolean isBound() 1240: { 1241: if (isClosed()) 1242: return false; 1243: if (impl instanceof PlainSocketImpl) 1244: { 1245: InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress(); 1246: return addr != null && addr.getAddress() != null; 1247: } 1248: return bound; 1249: } 1250: 1251: /** 1252: * Checks if the socket is closed. 1253: * 1254: * @return True if socket is closed, false otherwise. 1255: * 1256: * @since 1.4 1257: */ 1258: public boolean isClosed() 1259: { 1260: SocketChannel channel = getChannel(); 1261: 1262: return impl == null || (channel != null && ! channel.isOpen()); 1263: } 1264: 1265: /** 1266: * Checks if the socket's input stream is shutdown 1267: * 1268: * @return True if input is shut down. 1269: * 1270: * @since 1.4 1271: */ 1272: public boolean isInputShutdown() 1273: { 1274: return inputShutdown; 1275: } 1276: 1277: /** 1278: * Checks if the socket's output stream is shutdown 1279: * 1280: * @return True if output is shut down. 1281: * 1282: * @since 1.4 1283: */ 1284: public boolean isOutputShutdown() 1285: { 1286: return outputShutdown; 1287: } 1288: }
GNU Classpath (0.95) |