001/* Socket.java -- Client socket implementation 002 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007 003 Free Software Foundation, Inc. 004 005This file is part of GNU Classpath. 006 007GNU Classpath is free software; you can redistribute it and/or modify 008it under the terms of the GNU General Public License as published by 009the Free Software Foundation; either version 2, or (at your option) 010any later version. 011 012GNU Classpath is distributed in the hope that it will be useful, but 013WITHOUT ANY WARRANTY; without even the implied warranty of 014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015General Public License for more details. 016 017You should have received a copy of the GNU General Public License 018along with GNU Classpath; see the file COPYING. If not, write to the 019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02002110-1301 USA. 021 022Linking this library statically or dynamically with other modules is 023making a combined work based on this library. Thus, the terms and 024conditions of the GNU General Public License cover the whole 025combination. 026 027As a special exception, the copyright holders of this library give you 028permission to link this library with independent modules to produce an 029executable, regardless of the license terms of these independent 030modules, and to copy and distribute the resulting executable under 031terms of your choice, provided that you also meet, for each linked 032independent module, the terms and conditions of the license of that 033module. An independent module is a module which is not derived from 034or based on this library. If you modify this library, you may extend 035this exception to your version of the library, but you are not 036obligated to do so. If you do not wish to do so, delete this 037exception statement from your version. */ 038 039package java.net; 040 041import gnu.java.net.PlainSocketImpl; 042 043import java.io.IOException; 044import java.io.InputStream; 045import java.io.OutputStream; 046import java.nio.channels.IllegalBlockingModeException; 047import java.nio.channels.SocketChannel; 048 049 050/* Written using on-line Java Platform 1.2 API Specification. 051 * Status: I believe all methods are implemented. 052 */ 053 054/** 055 * This class models a client site socket. A socket is a TCP/IP endpoint 056 * for network communications conceptually similar to a file handle. 057 * <p> 058 * This class does not actually do any work. Instead, it redirects all of 059 * its calls to a socket implementation object which implements the 060 * <code>SocketImpl</code> interface. The implementation class is 061 * instantiated by factory class that implements the 062 * <code>SocketImplFactory interface</code>. A default 063 * factory is provided, however the factory may be set by a call to 064 * the <code>setSocketImplFactory</code> method. Note that this may only be 065 * done once per virtual machine. If a subsequent attempt is made to set the 066 * factory, a <code>SocketException</code> will be thrown. 067 * 068 * @author Aaron M. Renn (arenn@urbanophile.com) 069 * @author Per Bothner (bothner@cygnus.com) 070 */ 071public class Socket 072{ 073 /** 074 * This is the user SocketImplFactory for this class. If this variable is 075 * null, a default factory is used. 076 */ 077 static SocketImplFactory factory; 078 079 /** 080 * The implementation object to which calls are redirected 081 */ 082 // package-private because ServerSocket.implAccept() needs to access it. 083 SocketImpl impl; 084 085 /** 086 * True if impl.create() has been called. 087 */ 088 // package-private because ServerSocket.implAccept() needs to access it. 089 boolean implCreated; 090 091 /** 092 * True if the socket is bound. 093 * Package private so it can be set from ServerSocket when accept is called. 094 */ 095 boolean bound; 096 097 /** 098 * True if input is shutdown. 099 */ 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, Integer.valueOf(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, Integer.valueOf(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, Integer.valueOf(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, Integer.valueOf(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}