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