1 /* Socket.java -- Client socket implementation 2 Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007 3 Free Software Foundation, Inc. 4 5 This file is part of GNU Classpath. 6 7 GNU Classpath is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 GNU Classpath is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GNU Classpath; see the file COPYING. If not, write to the 19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301 USA. 21 22 Linking this library statically or dynamically with other modules is 23 making a combined work based on this library. Thus, the terms and 24 conditions of the GNU General Public License cover the whole 25 combination. 26 27 As a special exception, the copyright holders of this library give you 28 permission to link this library with independent modules to produce an 29 executable, regardless of the license terms of these independent 30 modules, and to copy and distribute the resulting executable under 31 terms of your choice, provided that you also meet, for each linked 32 independent module, the terms and conditions of the license of that 33 module. An independent module is a module which is not derived from 34 or based on this library. If you modify this library, you may extend 35 this exception to your version of the library, but you are not 36 obligated to do so. If you do not wish to do so, delete this 37 exception statement from your version. */ 38 39 package java.net; 40 41 import gnu.java.net.PlainSocketImpl; 42 43 import java.io.IOException; 44 import java.io.InputStream; 45 import java.io.OutputStream; 46 import java.nio.channels.IllegalBlockingModeException; 47 import java.nio.channels.SocketChannel; 48 49 50 /* Written using on-line Java Platform 1.2 API Specification. 51 * Status: I believe all methods are implemented. 52 */ 53 54 /** 55 * This class models a client site socket. A socket is a TCP/IP endpoint 56 * for network communications conceptually similar to a file handle. 57 * <p> 58 * This class does not actually do any work. Instead, it redirects all of 59 * its calls to a socket implementation object which implements the 60 * <code>SocketImpl</code> interface. The implementation class is 61 * instantiated by factory class that implements the 62 * <code>SocketImplFactory interface</code>. A default 63 * factory is provided, however the factory may be set by a call to 64 * the <code>setSocketImplFactory</code> method. Note that this may only be 65 * done once per virtual machine. If a subsequent attempt is made to set the 66 * factory, a <code>SocketException</code> will be thrown. 67 * 68 * @author Aaron M. Renn (arenn@urbanophile.com) 69 * @author Per Bothner (bothner@cygnus.com) 70 */ 71 public class Socket 72 { 73 /** 74 * This is the user SocketImplFactory for this class. If this variable is 75 * null, a default factory is used. 76 */ 77 static SocketImplFactory factory; 78 79 /** 80 * The implementation object to which calls are redirected 81 */ 82 // package-private because ServerSocket.implAccept() needs to access it. 83 SocketImpl impl; 84 85 /** 86 * True if impl.create() has been called. 87 */ 88 // package-private because ServerSocket.implAccept() needs to access it. 89 boolean implCreated; 90 91 /** 92 * True if the socket is bound. 93 * Package private so it can be set from ServerSocket when accept is called. 94 */ 95 boolean bound; 96 97 /** 98 * True if input is shutdown. 99 */ 100 private boolean inputShutdown; 101 102 /** 103 * True if output is shutdown. 104 */ 105 private boolean outputShutdown; 106 107 /** 108 * Initializes a new instance of <code>Socket</code> object without 109 * connecting to a remote host. This useful for subclasses of socket that 110 * might want this behavior. 111 * 112 * @specnote This constructor is public since JDK 1.4 113 * @since 1.1 114 */ Socket()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 */ Socket(SocketImpl impl)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 */ Socket(String host, int port)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 */ Socket(InetAddress address, int port)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 */ Socket(String host, int port, InetAddress localAddr, int localPort)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 */ Socket(InetAddress address, int port, InetAddress localAddr, int localPort)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 */ Socket(String host, int port, boolean stream)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 */ Socket(InetAddress host, int port, boolean stream)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 */ Socket(InetAddress raddr, int rport, InetAddress laddr, int lport, boolean stream)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 getImpl()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 */ bind(SocketAddress bindpoint)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 */ connect(SocketAddress endpoint)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 * @throws SecurityException if the SocketAddress is an {@link InetSocketAddress} 432 * and a security manager is present which does not 433 * allow connections on the given host and port. 434 * @since 1.4 435 */ connect(SocketAddress endpoint, int timeout)436 public void connect(SocketAddress endpoint, int timeout) 437 throws IOException 438 { 439 if (isClosed()) 440 throw new SocketException("socket is closed"); 441 442 if (! (endpoint instanceof InetSocketAddress)) 443 throw new IllegalArgumentException("unsupported address type"); 444 445 SecurityManager sm = System.getSecurityManager(); 446 if (sm != null) 447 { 448 InetSocketAddress inetAddr = (InetSocketAddress) endpoint; 449 sm.checkConnect(inetAddr.getHostName(), inetAddr.getPort()); 450 } 451 452 // The Sun spec says that if we have an associated channel and 453 // it is in non-blocking mode, we throw an IllegalBlockingModeException. 454 // However, in our implementation if the channel itself initiated this 455 // operation, then we must honor it regardless of its blocking mode. 456 if (getChannel() != null && ! getChannel().isBlocking() 457 && ! ((PlainSocketImpl) getImpl()).isInChannelOperation()) 458 throw new IllegalBlockingModeException(); 459 460 if (! isBound()) 461 bind(null); 462 463 getImpl().connect(endpoint, timeout); 464 } 465 466 /** 467 * Returns the address of the remote end of the socket. If this socket 468 * is not connected, then <code>null</code> is returned. 469 * 470 * @return The remote address this socket is connected to 471 */ getInetAddress()472 public InetAddress getInetAddress() 473 { 474 if (! isConnected()) 475 return null; 476 477 try 478 { 479 return getImpl().getInetAddress(); 480 } 481 catch (SocketException e) 482 { 483 // This cannot happen as we are connected. 484 } 485 486 return null; 487 } 488 489 /** 490 * Returns the local address to which this socket is bound. If this socket 491 * is not connected, then a wildcard address, for which 492 * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned. 493 * 494 * @return The local address 495 * 496 * @since 1.1 497 */ getLocalAddress()498 public InetAddress getLocalAddress() 499 { 500 if (! isBound()) 501 return InetAddress.ANY_IF; 502 503 InetAddress addr = null; 504 505 if (impl instanceof PlainSocketImpl) 506 addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress(); 507 508 if (addr == null) 509 { 510 try 511 { 512 addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); 513 } 514 catch (SocketException e) 515 { 516 // (hopefully) shouldn't happen 517 // throw new java.lang.InternalError 518 // ("Error in PlainSocketImpl.getOption"); 519 return null; 520 } 521 } 522 523 // FIXME: According to libgcj, checkConnect() is supposed to be called 524 // before performing this operation. Problems: 1) We don't have the 525 // addr until after we do it, so we do a post check. 2). The docs I 526 // see don't require this in the Socket case, only DatagramSocket, but 527 // we'll assume they mean both. 528 SecurityManager sm = System.getSecurityManager(); 529 if (sm != null) 530 sm.checkConnect(addr.getHostName(), getLocalPort()); 531 532 return addr; 533 } 534 535 /** 536 * Returns the port number of the remote end of the socket connection. If 537 * this socket is not connected, then 0 is returned. 538 * 539 * @return The remote port this socket is connected to 540 */ getPort()541 public int getPort() 542 { 543 if (! isConnected()) 544 return 0; 545 546 try 547 { 548 return getImpl().getPort(); 549 } 550 catch (SocketException e) 551 { 552 // This cannot happen as we are connected. 553 } 554 555 return 0; 556 } 557 558 /** 559 * Returns the local port number to which this socket is bound. If this 560 * socket is not connected, then -1 is returned. 561 * 562 * @return The local port 563 */ getLocalPort()564 public int getLocalPort() 565 { 566 if (! isBound()) 567 return -1; 568 569 try 570 { 571 if (getImpl() != null) 572 return getImpl().getLocalPort(); 573 } 574 catch (SocketException e) 575 { 576 // This cannot happen as we are bound. 577 } 578 579 return -1; 580 } 581 582 /** 583 * Returns local socket address. 584 * 585 * @return the local socket address, null if not bound 586 * 587 * @since 1.4 588 */ getLocalSocketAddress()589 public SocketAddress getLocalSocketAddress() 590 { 591 if (! isBound()) 592 return null; 593 594 InetAddress addr = getLocalAddress(); 595 596 try 597 { 598 return new InetSocketAddress(addr, getImpl().getLocalPort()); 599 } 600 catch (SocketException e) 601 { 602 // This cannot happen as we are bound. 603 return null; 604 } 605 } 606 607 /** 608 * Returns the remote socket address. 609 * 610 * @return the remote socket address, null of not connected 611 * 612 * @since 1.4 613 */ getRemoteSocketAddress()614 public SocketAddress getRemoteSocketAddress() 615 { 616 if (! isConnected()) 617 return null; 618 619 try 620 { 621 return new InetSocketAddress(getImpl().getInetAddress(), 622 getImpl().getPort()); 623 } 624 catch (SocketException e) 625 { 626 // This cannot happen as we are connected. 627 return null; 628 } 629 } 630 631 /** 632 * Returns an InputStream for reading from this socket. 633 * 634 * @return The InputStream object 635 * 636 * @exception IOException If an error occurs or Socket is not connected 637 */ getInputStream()638 public InputStream getInputStream() throws IOException 639 { 640 if (isClosed()) 641 throw new SocketException("socket is closed"); 642 643 if (! isConnected()) 644 throw new IOException("not connected"); 645 646 return getImpl().getInputStream(); 647 } 648 649 /** 650 * Returns an OutputStream for writing to this socket. 651 * 652 * @return The OutputStream object 653 * 654 * @exception IOException If an error occurs or Socket is not connected 655 */ getOutputStream()656 public OutputStream getOutputStream() throws IOException 657 { 658 if (isClosed()) 659 throw new SocketException("socket is closed"); 660 661 if (! isConnected()) 662 throw new IOException("not connected"); 663 664 return getImpl().getOutputStream(); 665 } 666 667 /** 668 * Sets the TCP_NODELAY option on the socket. 669 * 670 * @param on true to enable, false to disable 671 * 672 * @exception SocketException If an error occurs or Socket is not connected 673 * 674 * @since 1.1 675 */ setTcpNoDelay(boolean on)676 public void setTcpNoDelay(boolean on) throws SocketException 677 { 678 if (isClosed()) 679 throw new SocketException("socket is closed"); 680 681 getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); 682 } 683 684 /** 685 * Tests whether or not the TCP_NODELAY option is set on the socket. 686 * Returns true if enabled, false if disabled. When on it disables the 687 * Nagle algorithm which means that packets are always send immediatly and 688 * never merged together to reduce network trafic. 689 * 690 * @return Whether or not TCP_NODELAY is set 691 * 692 * @exception SocketException If an error occurs or Socket not connected 693 * 694 * @since 1.1 695 */ getTcpNoDelay()696 public boolean getTcpNoDelay() throws SocketException 697 { 698 if (isClosed()) 699 throw new SocketException("socket is closed"); 700 701 Object on = getImpl().getOption(SocketOptions.TCP_NODELAY); 702 703 if (on instanceof Boolean) 704 return (((Boolean) on).booleanValue()); 705 else 706 throw new SocketException("Internal Error"); 707 } 708 709 /** 710 * Sets the value of the SO_LINGER option on the socket. If the 711 * SO_LINGER option is set on a socket and there is still data waiting to 712 * be sent when the socket is closed, then the close operation will block 713 * until either that data is delivered or until the timeout period 714 * expires. The linger interval is specified in hundreths of a second 715 * (platform specific?) 716 * 717 * @param on true to enable SO_LINGER, false to disable 718 * @param linger The SO_LINGER timeout in hundreths of a second or -1 if 719 * SO_LINGER not set. 720 * 721 * @exception SocketException If an error occurs or Socket not connected 722 * @exception IllegalArgumentException If linger is negative 723 * 724 * @since 1.1 725 */ setSoLinger(boolean on, int linger)726 public void setSoLinger(boolean on, int linger) throws SocketException 727 { 728 if (isClosed()) 729 throw new SocketException("socket is closed"); 730 731 if (on) 732 { 733 if (linger < 0) 734 throw new IllegalArgumentException("SO_LINGER must be >= 0"); 735 736 if (linger > 65535) 737 linger = 65535; 738 739 getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger)); 740 } 741 else 742 getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1)); 743 } 744 745 /** 746 * Returns the value of the SO_LINGER option on the socket. If the 747 * SO_LINGER option is set on a socket and there is still data waiting to 748 * be sent when the socket is closed, then the close operation will block 749 * until either that data is delivered or until the timeout period 750 * expires. This method either returns the timeouts (in hundredths of 751 * of a second (platform specific?)) if SO_LINGER is set, or -1 if 752 * SO_LINGER is not set. 753 * 754 * @return The SO_LINGER timeout in hundreths of a second or -1 755 * if SO_LINGER not set 756 * 757 * @exception SocketException If an error occurs or Socket is not connected 758 * 759 * @since 1.1 760 */ getSoLinger()761 public int getSoLinger() throws SocketException 762 { 763 if (isClosed()) 764 throw new SocketException("socket is closed"); 765 766 Object linger = getImpl().getOption(SocketOptions.SO_LINGER); 767 768 if (linger instanceof Integer) 769 return (((Integer) linger).intValue()); 770 else 771 return -1; 772 } 773 774 /** 775 * Sends urgent data through the socket 776 * 777 * @param data The data to send. 778 * Only the lowest eight bits of data are sent 779 * 780 * @exception IOException If an error occurs 781 * 782 * @since 1.4 783 */ sendUrgentData(int data)784 public void sendUrgentData(int data) throws IOException 785 { 786 if (isClosed()) 787 throw new SocketException("socket is closed"); 788 789 getImpl().sendUrgentData(data); 790 } 791 792 /** 793 * Enables/disables the SO_OOBINLINE option 794 * 795 * @param on True if SO_OOBLINE should be enabled 796 * 797 * @exception SocketException If an error occurs 798 * 799 * @since 1.4 800 */ setOOBInline(boolean on)801 public void setOOBInline(boolean on) throws SocketException 802 { 803 if (isClosed()) 804 throw new SocketException("socket is closed"); 805 806 getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on)); 807 } 808 809 /** 810 * Returns the current setting of the SO_OOBINLINE option for this socket 811 * 812 * @return True if SO_OOBINLINE is set, false otherwise. 813 * 814 * @exception SocketException If an error occurs 815 * 816 * @since 1.4 817 */ getOOBInline()818 public boolean getOOBInline() throws SocketException 819 { 820 if (isClosed()) 821 throw new SocketException("socket is closed"); 822 823 Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE); 824 825 if (buf instanceof Boolean) 826 return (((Boolean) buf).booleanValue()); 827 else 828 throw new SocketException("Internal Error: Unexpected type"); 829 } 830 831 /** 832 * Sets the value of the SO_TIMEOUT option on the socket. If this value 833 * is set, and an read/write is performed that does not complete within 834 * the timeout period, a short count is returned (or an EWOULDBLOCK signal 835 * would be sent in Unix if no data had been read). A value of 0 for 836 * this option implies that there is no timeout (ie, operations will 837 * block forever). On systems that have separate read and write timeout 838 * values, this method returns the read timeout. This 839 * value is in milliseconds. 840 * 841 * @param timeout The length of the timeout in milliseconds, or 842 * 0 to indicate no timeout. 843 * 844 * @exception SocketException If an error occurs or Socket not connected 845 * 846 * @since 1.1 847 */ setSoTimeout(int timeout)848 public synchronized void setSoTimeout(int timeout) throws SocketException 849 { 850 if (isClosed()) 851 throw new SocketException("socket is closed"); 852 853 if (timeout < 0) 854 throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0"); 855 856 getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 857 } 858 859 /** 860 * Returns the value of the SO_TIMEOUT option on the socket. If this value 861 * is set, and an read/write is performed that does not complete within 862 * the timeout period, a short count is returned (or an EWOULDBLOCK signal 863 * would be sent in Unix if no data had been read). A value of 0 for 864 * this option implies that there is no timeout (ie, operations will 865 * block forever). On systems that have separate read and write timeout 866 * values, this method returns the read timeout. This 867 * value is in thousandths of a second (implementation specific?). 868 * 869 * @return The length of the timeout in thousandth's of a second or 0 870 * if not set 871 * 872 * @exception SocketException If an error occurs or Socket not connected 873 * 874 * @since 1.1 875 */ getSoTimeout()876 public synchronized int getSoTimeout() throws SocketException 877 { 878 if (isClosed()) 879 throw new SocketException("socket is closed"); 880 881 Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT); 882 if (timeout instanceof Integer) 883 return (((Integer) timeout).intValue()); 884 else 885 return 0; 886 } 887 888 /** 889 * This method sets the value for the system level socket option 890 * SO_SNDBUF to the specified value. Note that valid values for this 891 * option are specific to a given operating system. 892 * 893 * @param size The new send buffer size. 894 * 895 * @exception SocketException If an error occurs or Socket not connected 896 * @exception IllegalArgumentException If size is 0 or negative 897 * 898 * @since 1.2 899 */ setSendBufferSize(int size)900 public void setSendBufferSize(int size) throws SocketException 901 { 902 if (isClosed()) 903 throw new SocketException("socket is closed"); 904 905 if (size <= 0) 906 throw new IllegalArgumentException("SO_SNDBUF value must be > 0"); 907 908 getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 909 } 910 911 /** 912 * This method returns the value of the system level socket option 913 * SO_SNDBUF, which is used by the operating system to tune buffer 914 * sizes for data transfers. 915 * 916 * @return The send buffer size. 917 * 918 * @exception SocketException If an error occurs or socket not connected 919 * 920 * @since 1.2 921 */ getSendBufferSize()922 public int getSendBufferSize() throws SocketException 923 { 924 if (isClosed()) 925 throw new SocketException("socket is closed"); 926 927 Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF); 928 929 if (buf instanceof Integer) 930 return (((Integer) buf).intValue()); 931 else 932 throw new SocketException("Internal Error: Unexpected type"); 933 } 934 935 /** 936 * This method sets the value for the system level socket option 937 * SO_RCVBUF to the specified value. Note that valid values for this 938 * option are specific to a given operating system. 939 * 940 * @param size The new receive buffer size. 941 * 942 * @exception SocketException If an error occurs or Socket is not connected 943 * @exception IllegalArgumentException If size is 0 or negative 944 * 945 * @since 1.2 946 */ setReceiveBufferSize(int size)947 public void setReceiveBufferSize(int size) throws SocketException 948 { 949 if (isClosed()) 950 throw new SocketException("socket is closed"); 951 952 if (size <= 0) 953 throw new IllegalArgumentException("SO_RCVBUF value must be > 0"); 954 955 getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 956 } 957 958 /** 959 * This method returns the value of the system level socket option 960 * SO_RCVBUF, which is used by the operating system to tune buffer 961 * sizes for data transfers. 962 * 963 * @return The receive buffer size. 964 * 965 * @exception SocketException If an error occurs or Socket is not connected 966 * 967 * @since 1.2 968 */ getReceiveBufferSize()969 public int getReceiveBufferSize() throws SocketException 970 { 971 if (isClosed()) 972 throw new SocketException("socket is closed"); 973 974 Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF); 975 976 if (buf instanceof Integer) 977 return (((Integer) buf).intValue()); 978 else 979 throw new SocketException("Internal Error: Unexpected type"); 980 } 981 982 /** 983 * This method sets the value for the socket level socket option 984 * SO_KEEPALIVE. 985 * 986 * @param on True if SO_KEEPALIVE should be enabled 987 * 988 * @exception SocketException If an error occurs or Socket is not connected 989 * 990 * @since 1.3 991 */ setKeepAlive(boolean on)992 public void setKeepAlive(boolean on) throws SocketException 993 { 994 if (isClosed()) 995 throw new SocketException("socket is closed"); 996 997 getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on)); 998 } 999 1000 /** 1001 * This method returns the value of the socket level socket option 1002 * SO_KEEPALIVE. 1003 * 1004 * @return The setting 1005 * 1006 * @exception SocketException If an error occurs or Socket is not connected 1007 * 1008 * @since 1.3 1009 */ getKeepAlive()1010 public boolean getKeepAlive() throws SocketException 1011 { 1012 if (isClosed()) 1013 throw new SocketException("socket is closed"); 1014 1015 Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE); 1016 1017 if (buf instanceof Boolean) 1018 return (((Boolean) buf).booleanValue()); 1019 else 1020 throw new SocketException("Internal Error: Unexpected type"); 1021 } 1022 1023 /** 1024 * Closes the socket. 1025 * 1026 * @exception IOException If an error occurs 1027 */ close()1028 public synchronized void close() throws IOException 1029 { 1030 if (isClosed()) 1031 return; 1032 1033 impl.close(); 1034 impl = null; 1035 } 1036 1037 /** 1038 * Converts this <code>Socket</code> to a <code>String</code>. 1039 * 1040 * @return The <code>String</code> representation of this <code>Socket</code> 1041 */ toString()1042 public String toString() 1043 { 1044 try 1045 { 1046 if (isConnected()) 1047 return (super.toString() 1048 + " [addr=" + getImpl().getInetAddress() + ",port=" 1049 + getImpl().getPort() + ",localport=" 1050 + getImpl().getLocalPort() + "]"); 1051 } 1052 catch (SocketException e) 1053 { 1054 // This cannot happen as we are connected. 1055 } 1056 1057 return super.toString() + " [unconnected]"; 1058 } 1059 1060 /** 1061 * Sets the <code>SocketImplFactory</code>. This may be done only once per 1062 * virtual machine. Subsequent attempts will generate a 1063 * <code>SocketException</code>. Note that a <code>SecurityManager</code> 1064 * check is made prior to setting the factory. If 1065 * insufficient privileges exist to set the factory, then an 1066 * <code>IOException</code> will be thrown. 1067 * 1068 * @param fac the factory to set 1069 * 1070 * @exception SecurityException If the <code>SecurityManager</code> does 1071 * not allow this operation. 1072 * @exception SocketException If the SocketImplFactory is already defined 1073 * @exception IOException If any other error occurs 1074 */ setSocketImplFactory(SocketImplFactory fac)1075 public static synchronized void setSocketImplFactory(SocketImplFactory fac) 1076 throws IOException 1077 { 1078 // See if already set 1079 if (factory != null) 1080 throw new SocketException("SocketImplFactory already defined"); 1081 1082 // Check permissions 1083 SecurityManager sm = System.getSecurityManager(); 1084 if (sm != null) 1085 sm.checkSetFactory(); 1086 1087 if (fac == null) 1088 throw new SocketException("SocketImplFactory cannot be null"); 1089 1090 factory = fac; 1091 } 1092 1093 /** 1094 * Closes the input side of the socket stream. 1095 * 1096 * @exception IOException If an error occurs. 1097 * 1098 * @since 1.3 1099 */ shutdownInput()1100 public void shutdownInput() throws IOException 1101 { 1102 if (isClosed()) 1103 throw new SocketException("socket is closed"); 1104 1105 getImpl().shutdownInput(); 1106 inputShutdown = true; 1107 } 1108 1109 /** 1110 * Closes the output side of the socket stream. 1111 * 1112 * @exception IOException If an error occurs. 1113 * 1114 * @since 1.3 1115 */ shutdownOutput()1116 public void shutdownOutput() throws IOException 1117 { 1118 if (isClosed()) 1119 throw new SocketException("socket is closed"); 1120 1121 getImpl().shutdownOutput(); 1122 outputShutdown = true; 1123 } 1124 1125 /** 1126 * Returns the socket channel associated with this socket. 1127 * 1128 * @return the associated socket channel, 1129 * null if no associated channel exists 1130 * 1131 * @since 1.4 1132 */ getChannel()1133 public SocketChannel getChannel() 1134 { 1135 return null; 1136 } 1137 1138 /** 1139 * Checks if the SO_REUSEADDR option is enabled 1140 * 1141 * @return True if SO_REUSEADDR is set, false otherwise. 1142 * 1143 * @exception SocketException If an error occurs 1144 * 1145 * @since 1.4 1146 */ getReuseAddress()1147 public boolean getReuseAddress() throws SocketException 1148 { 1149 if (isClosed()) 1150 throw new SocketException("socket is closed"); 1151 1152 Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR); 1153 1154 if (! (reuseaddr instanceof Boolean)) 1155 throw new SocketException("Internal Error"); 1156 1157 return ((Boolean) reuseaddr).booleanValue(); 1158 } 1159 1160 /** 1161 * Enables/Disables the SO_REUSEADDR option 1162 * 1163 * @param reuseAddress true if SO_REUSEADDR should be enabled, 1164 * false otherwise 1165 * 1166 * @exception SocketException If an error occurs 1167 * 1168 * @since 1.4 1169 */ setReuseAddress(boolean reuseAddress)1170 public void setReuseAddress(boolean reuseAddress) throws SocketException 1171 { 1172 if (isClosed()) 1173 throw new SocketException("socket is closed"); 1174 1175 getImpl().setOption(SocketOptions.SO_REUSEADDR, 1176 Boolean.valueOf(reuseAddress)); 1177 } 1178 1179 /** 1180 * Returns the current traffic class 1181 * 1182 * @return The current traffic class. 1183 * 1184 * @exception SocketException If an error occurs 1185 * 1186 * @see Socket#setTrafficClass(int tc) 1187 * 1188 * @since 1.4 1189 */ getTrafficClass()1190 public int getTrafficClass() throws SocketException 1191 { 1192 if (isClosed()) 1193 throw new SocketException("socket is closed"); 1194 1195 Object obj = getImpl().getOption(SocketOptions.IP_TOS); 1196 1197 if (obj instanceof Integer) 1198 return ((Integer) obj).intValue(); 1199 else 1200 throw new SocketException("Unexpected type"); 1201 } 1202 1203 /** 1204 * Sets the traffic class value 1205 * 1206 * @param tc The traffic class 1207 * 1208 * @exception SocketException If an error occurs 1209 * @exception IllegalArgumentException If tc value is illegal 1210 * 1211 * @see Socket#getTrafficClass() 1212 * 1213 * @since 1.4 1214 */ setTrafficClass(int tc)1215 public void setTrafficClass(int tc) throws SocketException 1216 { 1217 if (isClosed()) 1218 throw new SocketException("socket is closed"); 1219 1220 if (tc < 0 || tc > 255) 1221 throw new IllegalArgumentException(); 1222 1223 getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc)); 1224 } 1225 1226 /** 1227 * Checks if the socket is connected 1228 * 1229 * @return True if socket is connected, false otherwise. 1230 * 1231 * @since 1.4 1232 */ isConnected()1233 public boolean isConnected() 1234 { 1235 if (impl == null) 1236 return false; 1237 1238 return impl.getInetAddress() != null; 1239 } 1240 1241 /** 1242 * Checks if the socket is already bound. 1243 * 1244 * @return True if socket is bound, false otherwise. 1245 * 1246 * @since 1.4 1247 */ isBound()1248 public boolean isBound() 1249 { 1250 if (isClosed()) 1251 return false; 1252 if (impl instanceof PlainSocketImpl) 1253 { 1254 InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress(); 1255 return addr != null && addr.getAddress() != null; 1256 } 1257 return bound; 1258 } 1259 1260 /** 1261 * Checks if the socket is closed. 1262 * 1263 * @return True if socket is closed, false otherwise. 1264 * 1265 * @since 1.4 1266 */ isClosed()1267 public boolean isClosed() 1268 { 1269 SocketChannel channel = getChannel(); 1270 1271 return impl == null || (channel != null && ! channel.isOpen()); 1272 } 1273 1274 /** 1275 * Checks if the socket's input stream is shutdown 1276 * 1277 * @return True if input is shut down. 1278 * 1279 * @since 1.4 1280 */ isInputShutdown()1281 public boolean isInputShutdown() 1282 { 1283 return inputShutdown; 1284 } 1285 1286 /** 1287 * Checks if the socket's output stream is shutdown 1288 * 1289 * @return True if output is shut down. 1290 * 1291 * @since 1.4 1292 */ isOutputShutdown()1293 public boolean isOutputShutdown() 1294 { 1295 return outputShutdown; 1296 } 1297 } 1298