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