1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package java.net; 19 20 import java.io.Closeable; 21 import java.io.FileDescriptor; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.OutputStream; 25 import java.nio.channels.SocketChannel; 26 import libcore.io.IoBridge; 27 28 /** 29 * Provides a client-side TCP socket. 30 */ 31 public class Socket implements Closeable { 32 private static SocketImplFactory factory; 33 34 final SocketImpl impl; 35 private final Proxy proxy; 36 37 volatile boolean isCreated = false; 38 private boolean isBound = false; 39 private boolean isConnected = false; 40 private boolean isClosed = false; 41 private boolean isInputShutdown = false; 42 private boolean isOutputShutdown = false; 43 44 private InetAddress localAddress = Inet4Address.ANY; 45 46 private final Object connectLock = new Object(); 47 48 /** 49 * Creates a new unconnected socket. When a SocketImplFactory is defined it 50 * creates the internal socket implementation, otherwise the default socket 51 * implementation will be used for this socket. 52 * 53 * @see SocketImplFactory 54 * @see SocketImpl 55 */ 56 public Socket() { 57 this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(); 58 this.proxy = null; 59 } 60 61 /** 62 * Creates a new unconnected socket using the given proxy type. When a 63 * {@code SocketImplFactory} is defined it creates the internal socket 64 * implementation, otherwise the default socket implementation will be used 65 * for this socket. 66 * <p> 67 * Example that will create a socket connection through a {@code SOCKS} 68 * proxy server: <br> 69 * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new 70 * InetSocketAddress("test.domain.org", 2130)));} 71 * 72 * @param proxy 73 * the specified proxy for this socket. 74 * @throws IllegalArgumentException 75 * if the argument {@code proxy} is {@code null} or of an 76 * invalid type. 77 * @see SocketImplFactory 78 * @see SocketImpl 79 */ 80 public Socket(Proxy proxy) { 81 if (proxy == null || proxy.type() == Proxy.Type.HTTP) { 82 throw new IllegalArgumentException("Invalid proxy: " + proxy); 83 } 84 this.proxy = proxy; 85 this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(proxy); 86 } 87 88 /** 89 * Tries to connect a socket to all IP addresses of the given hostname. 90 * 91 * @param dstName 92 * the target host name or IP address to connect to. 93 * @param dstPort 94 * the port on the target host to connect to. 95 * @param localAddress 96 * the address on the local host to bind to. 97 * @param localPort 98 * the port on the local host to bind to. 99 * @param streaming 100 * if {@code true} a streaming socket is returned, a datagram 101 * socket otherwise. 102 * @throws UnknownHostException 103 * if the host name could not be resolved into an IP address. 104 * @throws IOException 105 * if an error occurs while creating the socket. 106 */ 107 private void tryAllAddresses(String dstName, int dstPort, InetAddress 108 localAddress, int localPort, boolean streaming) throws IOException { 109 InetAddress[] dstAddresses = InetAddress.getAllByName(dstName); 110 // Loop through all the destination addresses except the last, trying to 111 // connect to each one and ignoring errors. There must be at least one 112 // address, or getAllByName would have thrown UnknownHostException. 113 InetAddress dstAddress; 114 for (int i = 0; i < dstAddresses.length - 1; i++) { 115 dstAddress = dstAddresses[i]; 116 try { 117 checkDestination(dstAddress, dstPort); 118 startupSocket(dstAddress, dstPort, localAddress, localPort, streaming); 119 return; 120 } catch (IOException ex) { 121 } 122 } 123 124 // Now try to connect to the last address in the array, handing back to 125 // the caller any exceptions that are thrown. 126 dstAddress = dstAddresses[dstAddresses.length - 1]; 127 checkDestination(dstAddress, dstPort); 128 startupSocket(dstAddress, dstPort, localAddress, localPort, streaming); 129 } 130 131 /** 132 * Creates a new streaming socket connected to the target host specified by 133 * the parameters {@code dstName} and {@code dstPort}. The socket is bound 134 * to any available port on the local host. 135 * 136 * <p>This implementation tries each IP address for the given hostname (in 137 * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order) 138 * until it either connects successfully or it exhausts the set. 139 * 140 * @param dstName 141 * the target host name or IP address to connect to. 142 * @param dstPort 143 * the port on the target host to connect to. 144 * @throws UnknownHostException 145 * if the host name could not be resolved into an IP address. 146 * @throws IOException 147 * if an error occurs while creating the socket. 148 */ 149 public Socket(String dstName, int dstPort) throws UnknownHostException, IOException { 150 this(dstName, dstPort, null, 0); 151 } 152 153 /** 154 * Creates a new streaming socket connected to the target host specified by 155 * the parameters {@code dstName} and {@code dstPort}. On the local endpoint 156 * the socket is bound to the given address {@code localAddress} on port 157 * {@code localPort}. If {@code host} is {@code null} a loopback address is used to connect to. 158 * 159 * <p>This implementation tries each IP address for the given hostname (in 160 * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order) 161 * until it either connects successfully or it exhausts the set. 162 * 163 * @param dstName 164 * the target host name or IP address to connect to. 165 * @param dstPort 166 * the port on the target host to connect to. 167 * @param localAddress 168 * the address on the local host to bind to. 169 * @param localPort 170 * the port on the local host to bind to. 171 * @throws UnknownHostException 172 * if the host name could not be resolved into an IP address. 173 * @throws IOException 174 * if an error occurs while creating the socket. 175 */ 176 public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException { 177 this(); 178 tryAllAddresses(dstName, dstPort, localAddress, localPort, true); 179 } 180 181 /** 182 * Creates a new streaming or datagram socket connected to the target host 183 * specified by the parameters {@code hostName} and {@code port}. The socket 184 * is bound to any available port on the local host. 185 * 186 * <p>This implementation tries each IP address for the given hostname (in 187 * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order) 188 * until it either connects successfully or it exhausts the set. 189 * 190 * @param hostName 191 * the target host name or IP address to connect to. 192 * @param port 193 * the port on the target host to connect to. 194 * @param streaming 195 * if {@code true} a streaming socket is returned, a datagram 196 * socket otherwise. 197 * @throws UnknownHostException 198 * if the host name could not be resolved into an IP address. 199 * @throws IOException 200 * if an error occurs while creating the socket. 201 * @deprecated Use {@code Socket(String, int)} instead of this for streaming 202 * sockets or an appropriate constructor of {@code 203 * DatagramSocket} for UDP transport. 204 */ 205 @Deprecated 206 public Socket(String hostName, int port, boolean streaming) throws IOException { 207 this(); 208 tryAllAddresses(hostName, port, null, 0, streaming); 209 } 210 211 /** 212 * Creates a new streaming socket connected to the target host specified by 213 * the parameters {@code dstAddress} and {@code dstPort}. The socket is 214 * bound to any available port on the local host. 215 * 216 * @param dstAddress 217 * the target host address to connect to. 218 * @param dstPort 219 * the port on the target host to connect to. 220 * @throws IOException 221 * if an error occurs while creating the socket. 222 */ 223 public Socket(InetAddress dstAddress, int dstPort) throws IOException { 224 this(); 225 checkDestination(dstAddress, dstPort); 226 startupSocket(dstAddress, dstPort, null, 0, true); 227 } 228 229 /** 230 * Creates a new streaming socket connected to the target host specified by 231 * the parameters {@code dstAddress} and {@code dstPort}. On the local 232 * endpoint the socket is bound to the given address {@code localAddress} on 233 * port {@code localPort}. 234 * 235 * @param dstAddress 236 * the target host address to connect to. 237 * @param dstPort 238 * the port on the target host to connect to. 239 * @param localAddress 240 * the address on the local host to bind to. 241 * @param localPort 242 * the port on the local host to bind to. 243 * @throws IOException 244 * if an error occurs while creating the socket. 245 */ 246 public Socket(InetAddress dstAddress, int dstPort, 247 InetAddress localAddress, int localPort) throws IOException { 248 this(); 249 checkDestination(dstAddress, dstPort); 250 startupSocket(dstAddress, dstPort, localAddress, localPort, true); 251 } 252 253 /** 254 * Creates a new streaming or datagram socket connected to the target host 255 * specified by the parameters {@code addr} and {@code port}. The socket is 256 * bound to any available port on the local host. 257 * 258 * @param addr 259 * the Internet address to connect to. 260 * @param port 261 * the port on the target host to connect to. 262 * @param streaming 263 * if {@code true} a streaming socket is returned, a datagram 264 * socket otherwise. 265 * @throws IOException 266 * if an error occurs while creating the socket. 267 * @deprecated Use {@code Socket(InetAddress, int)} instead of this for 268 * streaming sockets or an appropriate constructor of {@code 269 * DatagramSocket} for UDP transport. 270 */ 271 @Deprecated 272 public Socket(InetAddress addr, int port, boolean streaming) throws IOException { 273 this(); 274 checkDestination(addr, port); 275 startupSocket(addr, port, null, 0, streaming); 276 } 277 278 /** 279 * Creates an unconnected socket with the given socket implementation. 280 * 281 * @param impl 282 * the socket implementation to be used. 283 * @throws SocketException 284 * if an error occurs while creating the socket. 285 */ 286 protected Socket(SocketImpl impl) throws SocketException { 287 this.impl = impl; 288 this.proxy = null; 289 } 290 291 /** 292 * Checks whether the connection destination satisfies the security policy 293 * and the validity of the port range. 294 * 295 * @param destAddr 296 * the destination host address. 297 * @param dstPort 298 * the port on the destination host. 299 */ 300 private void checkDestination(InetAddress destAddr, int dstPort) { 301 if (dstPort < 0 || dstPort > 65535) { 302 throw new IllegalArgumentException("Port out of range: " + dstPort); 303 } 304 } 305 306 /** 307 * Closes the socket. It is not possible to reconnect or rebind to this 308 * socket thereafter which means a new socket instance has to be created. 309 * 310 * @throws IOException 311 * if an error occurs while closing the socket. 312 */ 313 public synchronized void close() throws IOException { 314 isClosed = true; 315 isConnected = false; 316 // RI compatibility: the RI returns the any address (but the original local port) after 317 // close. 318 localAddress = Inet4Address.ANY; 319 impl.close(); 320 } 321 322 /** 323 * Sets the Socket and its related SocketImpl state as if a successful close() took place, 324 * without actually performing an OS close(). 325 * 326 * @hide used in java.nio 327 */ 328 public void onClose() { 329 isClosed = true; 330 isConnected = false; 331 // RI compatibility: the RI returns the any address (but the original local port) after 332 // close. 333 localAddress = Inet4Address.ANY; 334 impl.onClose(); 335 } 336 337 /** 338 * Returns the IP address of the target host this socket is connected to, or null if this 339 * socket is not yet connected. 340 */ 341 public InetAddress getInetAddress() { 342 if (!isConnected()) { 343 return null; 344 } 345 return impl.getInetAddress(); 346 } 347 348 /** 349 * Returns an input stream to read data from this socket. If the socket has an associated 350 * {@link SocketChannel} and that channel is in non-blocking mode then reads from the 351 * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}. 352 * 353 * @return the byte-oriented input stream. 354 * @throws IOException 355 * if an error occurs while creating the input stream or the 356 * socket is in an invalid state. 357 */ 358 public InputStream getInputStream() throws IOException { 359 checkOpenAndCreate(false); 360 if (isInputShutdown()) { 361 throw new SocketException("Socket input is shutdown"); 362 } 363 return impl.getInputStream(); 364 } 365 366 /** 367 * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting. 368 */ 369 public boolean getKeepAlive() throws SocketException { 370 checkOpenAndCreate(true); 371 return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE); 372 } 373 374 /** 375 * Returns the local IP address this socket is bound to, or an address for which 376 * {@link InetAddress#isAnyLocalAddress()} returns true if the socket is closed or unbound. 377 */ 378 public InetAddress getLocalAddress() { 379 return localAddress; 380 } 381 382 /** 383 * Returns the local port this socket is bound to, or -1 if the socket is unbound. If the socket 384 * has been closed this method will still return the local port the socket was bound to. 385 */ 386 public int getLocalPort() { 387 if (!isBound()) { 388 return -1; 389 } 390 return impl.getLocalPort(); 391 } 392 393 /** 394 * Returns an output stream to write data into this socket. If the socket has an associated 395 * {@link SocketChannel} and that channel is in non-blocking mode then writes to the 396 * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}. 397 * 398 * @return the byte-oriented output stream. 399 * @throws IOException 400 * if an error occurs while creating the output stream or the 401 * socket is in an invalid state. 402 */ 403 public OutputStream getOutputStream() throws IOException { 404 checkOpenAndCreate(false); 405 if (isOutputShutdown()) { 406 throw new SocketException("Socket output is shutdown"); 407 } 408 return impl.getOutputStream(); 409 } 410 411 /** 412 * Returns the port number of the target host this socket is connected to, or 0 if this socket 413 * is not yet connected. 414 */ 415 public int getPort() { 416 if (!isConnected()) { 417 return 0; 418 } 419 return impl.getPort(); 420 } 421 422 /** 423 * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1 424 * for no linger (i.e. {@code close} will return immediately). 425 */ 426 public int getSoLinger() throws SocketException { 427 checkOpenAndCreate(true); 428 // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation. 429 Object value = impl.getOption(SocketOptions.SO_LINGER); 430 if (value instanceof Integer) { 431 return (Integer) value; 432 } else { 433 return -1; 434 } 435 } 436 437 /** 438 * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}. 439 */ 440 public synchronized int getReceiveBufferSize() throws SocketException { 441 checkOpenAndCreate(true); 442 return (Integer) impl.getOption(SocketOptions.SO_RCVBUF); 443 } 444 445 /** 446 * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}. 447 */ 448 public synchronized int getSendBufferSize() throws SocketException { 449 checkOpenAndCreate(true); 450 return (Integer) impl.getOption(SocketOptions.SO_SNDBUF); 451 } 452 453 /** 454 * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}. 455 */ 456 public synchronized int getSoTimeout() throws SocketException { 457 checkOpenAndCreate(true); 458 return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT); 459 } 460 461 /** 462 * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting. 463 */ 464 public boolean getTcpNoDelay() throws SocketException { 465 checkOpenAndCreate(true); 466 return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY); 467 } 468 469 /** 470 * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option. 471 */ 472 public void setKeepAlive(boolean keepAlive) throws SocketException { 473 if (impl != null) { 474 checkOpenAndCreate(true); 475 impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive)); 476 } 477 } 478 479 /** 480 * Sets the internal factory for creating socket implementations. This may 481 * only be executed once during the lifetime of the application. 482 * 483 * @param fac 484 * the socket implementation factory to be set. 485 * @throws IOException 486 * if the factory has been already set. 487 */ 488 public static synchronized void setSocketImplFactory(SocketImplFactory fac) 489 throws IOException { 490 if (factory != null) { 491 throw new SocketException("Factory already set"); 492 } 493 factory = fac; 494 } 495 496 /** 497 * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}. 498 */ 499 public synchronized void setSendBufferSize(int size) throws SocketException { 500 checkOpenAndCreate(true); 501 if (size < 1) { 502 throw new IllegalArgumentException("size < 1"); 503 } 504 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 505 } 506 507 /** 508 * Sets this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}. 509 */ 510 public synchronized void setReceiveBufferSize(int size) throws SocketException { 511 checkOpenAndCreate(true); 512 if (size < 1) { 513 throw new IllegalArgumentException("size < 1"); 514 } 515 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 516 } 517 518 /** 519 * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds. 520 * If {@code on} is false, {@code timeout} is irrelevant. 521 */ 522 public void setSoLinger(boolean on, int timeout) throws SocketException { 523 checkOpenAndCreate(true); 524 // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation. 525 if (on && timeout < 0) { 526 throw new IllegalArgumentException("timeout < 0"); 527 } 528 if (on) { 529 impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout)); 530 } else { 531 impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE); 532 } 533 } 534 535 /** 536 * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds. 537 * Use 0 for no timeout. 538 * To take effect, this option must be set before the blocking method was called. 539 */ 540 public synchronized void setSoTimeout(int timeout) throws SocketException { 541 checkOpenAndCreate(true); 542 if (timeout < 0) { 543 throw new IllegalArgumentException("timeout < 0"); 544 } 545 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 546 } 547 548 /** 549 * Sets this socket's {@link SocketOptions#TCP_NODELAY} option. 550 */ 551 public void setTcpNoDelay(boolean on) throws SocketException { 552 checkOpenAndCreate(true); 553 impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); 554 } 555 556 /** 557 * Creates a stream socket, binds it to the nominated local address/port, 558 * then connects it to the nominated destination address/port. 559 * 560 * @param dstAddress 561 * the destination host address. 562 * @param dstPort 563 * the port on the destination host. 564 * @param localAddress 565 * the address on the local machine to bind. 566 * @param localPort 567 * the port on the local machine to bind. 568 * @throws IOException 569 * thrown if an error occurs during the bind or connect 570 * operations. 571 */ 572 private void startupSocket(InetAddress dstAddress, int dstPort, 573 InetAddress localAddress, int localPort, boolean streaming) 574 throws IOException { 575 576 if (localPort < 0 || localPort > 65535) { 577 throw new IllegalArgumentException("Local port out of range: " + localPort); 578 } 579 580 InetAddress addr = localAddress == null ? Inet4Address.ANY : localAddress; 581 synchronized (this) { 582 impl.create(streaming); 583 isCreated = true; 584 try { 585 if (!streaming || !usingSocks()) { 586 impl.bind(addr, localPort); 587 } 588 isBound = true; 589 cacheLocalAddress(); 590 impl.connect(dstAddress, dstPort); 591 isConnected = true; 592 cacheLocalAddress(); 593 } catch (IOException e) { 594 impl.close(); 595 throw e; 596 } 597 } 598 } 599 600 private boolean usingSocks() { 601 return proxy != null && proxy.type() == Proxy.Type.SOCKS; 602 } 603 604 /** 605 * Returns a {@code String} containing a concise, human-readable description of the 606 * socket. 607 * 608 * @return the textual representation of this socket. 609 */ 610 @Override 611 public String toString() { 612 if (!isConnected()) { 613 return "Socket[unconnected]"; 614 } 615 return impl.toString(); 616 } 617 618 /** 619 * Closes the input stream of this socket. Any further data sent to this 620 * socket will be discarded. Reading from this socket after this method has 621 * been called will return the value {@code EOF}. 622 * 623 * @throws IOException 624 * if an error occurs while closing the socket input stream. 625 * @throws SocketException 626 * if the input stream is already closed. 627 */ 628 public void shutdownInput() throws IOException { 629 if (isInputShutdown()) { 630 throw new SocketException("Socket input is shutdown"); 631 } 632 checkOpenAndCreate(false); 633 impl.shutdownInput(); 634 isInputShutdown = true; 635 } 636 637 /** 638 * Closes the output stream of this socket. All buffered data will be sent 639 * followed by the termination sequence. Writing to the closed output stream 640 * will cause an {@code IOException}. 641 * 642 * @throws IOException 643 * if an error occurs while closing the socket output stream. 644 * @throws SocketException 645 * if the output stream is already closed. 646 */ 647 public void shutdownOutput() throws IOException { 648 if (isOutputShutdown()) { 649 throw new SocketException("Socket output is shutdown"); 650 } 651 checkOpenAndCreate(false); 652 impl.shutdownOutput(); 653 isOutputShutdown = true; 654 } 655 656 /** 657 * Checks whether the socket is closed, and throws an exception. Otherwise 658 * creates the underlying SocketImpl. 659 * 660 * @throws SocketException 661 * if the socket is closed. 662 */ 663 private void checkOpenAndCreate(boolean create) throws SocketException { 664 if (isClosed()) { 665 throw new SocketException("Socket is closed"); 666 } 667 if (!create) { 668 if (!isConnected()) { 669 throw new SocketException("Socket is not connected"); 670 // a connected socket must be created 671 } 672 673 /* 674 * return directly to fix a possible bug, if !create, should return 675 * here 676 */ 677 return; 678 } 679 if (isCreated) { 680 return; 681 } 682 synchronized (this) { 683 if (isCreated) { 684 return; 685 } 686 try { 687 impl.create(true); 688 } catch (SocketException e) { 689 throw e; 690 } catch (IOException e) { 691 throw new SocketException(e.toString()); 692 } 693 isCreated = true; 694 } 695 } 696 697 /** 698 * Returns the local address and port of this socket as a SocketAddress or null if the socket 699 * has never been bound. If the socket is closed but has previously been bound then an address 700 * for which {@link InetAddress#isAnyLocalAddress()} returns true will be returned with the 701 * previously-bound port. This is useful on multihomed hosts. 702 */ 703 public SocketAddress getLocalSocketAddress() { 704 if (!isBound()) { 705 return null; 706 } 707 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 708 } 709 710 /** 711 * Returns the remote address and port of this socket as a {@code 712 * SocketAddress} or null if the socket is not connected. 713 * 714 * @return the remote socket address and port. 715 */ 716 public SocketAddress getRemoteSocketAddress() { 717 if (!isConnected()) { 718 return null; 719 } 720 return new InetSocketAddress(getInetAddress(), getPort()); 721 } 722 723 /** 724 * Returns whether this socket is bound to a local address and port. 725 * 726 * @return {@code true} if the socket is bound to a local address, {@code 727 * false} otherwise. 728 */ 729 public boolean isBound() { 730 return isBound; 731 } 732 733 /** 734 * Returns whether this socket is connected to a remote host. 735 * 736 * @return {@code true} if the socket is connected, {@code false} otherwise. 737 */ 738 public boolean isConnected() { 739 return isConnected; 740 } 741 742 /** 743 * Returns whether this socket is closed. 744 * 745 * @return {@code true} if the socket is closed, {@code false} otherwise. 746 */ 747 public boolean isClosed() { 748 return isClosed; 749 } 750 751 /** 752 * Binds this socket to the given local host address and port specified by 753 * the SocketAddress {@code localAddr}. If {@code localAddr} is set to 754 * {@code null}, this socket will be bound to an available local address on 755 * any free port. 756 * 757 * @param localAddr 758 * the specific address and port on the local machine to bind to. 759 * @throws IllegalArgumentException 760 * if the given SocketAddress is invalid or not supported. 761 * @throws IOException 762 * if the socket is already bound or an error occurs while 763 * binding. 764 */ 765 public void bind(SocketAddress localAddr) throws IOException { 766 checkOpenAndCreate(true); 767 if (isBound()) { 768 throw new BindException("Socket is already bound"); 769 } 770 771 int port; 772 InetAddress addr; 773 if (localAddr == null) { 774 port = 0; 775 addr = Inet4Address.ANY; 776 } else { 777 if (!(localAddr instanceof InetSocketAddress)) { 778 throw new IllegalArgumentException("Local address not an InetSocketAddress: " + 779 localAddr.getClass()); 780 } 781 InetSocketAddress inetAddr = (InetSocketAddress) localAddr; 782 if ((addr = inetAddr.getAddress()) == null) { 783 throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName()); 784 } 785 port = inetAddr.getPort(); 786 } 787 788 synchronized (this) { 789 try { 790 impl.bind(addr, port); 791 isBound = true; 792 cacheLocalAddress(); 793 } catch (IOException e) { 794 impl.close(); 795 throw e; 796 } 797 } 798 } 799 800 /** 801 * Sets the Socket and its related SocketImpl state as if a successful bind() took place, 802 * without actually performing an OS bind(). 803 * 804 * @hide used in java.nio 805 */ 806 public void onBind(InetAddress localAddress, int localPort) { 807 isBound = true; 808 this.localAddress = localAddress; 809 impl.onBind(localAddress, localPort); 810 } 811 812 /** 813 * Connects this socket to the given remote host address and port specified 814 * by the SocketAddress {@code remoteAddr}. 815 * 816 * @param remoteAddr 817 * the address and port of the remote host to connect to. 818 * @throws IllegalArgumentException 819 * if the given SocketAddress is invalid or not supported. 820 * @throws IOException 821 * if the socket is already connected or an error occurs while 822 * connecting. 823 */ 824 public void connect(SocketAddress remoteAddr) throws IOException { 825 connect(remoteAddr, 0); 826 } 827 828 /** 829 * Connects this socket to the given remote host address and port specified 830 * by the SocketAddress {@code remoteAddr} with the specified timeout. The 831 * connecting method will block until the connection is established or an 832 * error occurred. 833 * 834 * @param remoteAddr 835 * the address and port of the remote host to connect to. 836 * @param timeout 837 * the timeout value in milliseconds or {@code 0} for an infinite 838 * timeout. 839 * @throws IllegalArgumentException 840 * if the given SocketAddress is invalid or not supported or the 841 * timeout value is negative. 842 * @throws IOException 843 * if the socket is already connected or an error occurs while 844 * connecting. 845 */ 846 public void connect(SocketAddress remoteAddr, int timeout) throws IOException { 847 checkOpenAndCreate(true); 848 if (timeout < 0) { 849 throw new IllegalArgumentException("timeout < 0"); 850 } 851 if (isConnected()) { 852 throw new SocketException("Already connected"); 853 } 854 if (remoteAddr == null) { 855 throw new IllegalArgumentException("remoteAddr == null"); 856 } 857 858 if (!(remoteAddr instanceof InetSocketAddress)) { 859 throw new IllegalArgumentException("Remote address not an InetSocketAddress: " + 860 remoteAddr.getClass()); 861 } 862 InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 863 InetAddress addr; 864 if ((addr = inetAddr.getAddress()) == null) { 865 throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName()); 866 } 867 int port = inetAddr.getPort(); 868 869 checkDestination(addr, port); 870 synchronized (connectLock) { 871 try { 872 if (!isBound()) { 873 // socket already created at this point by earlier call or 874 // checkOpenAndCreate this caused us to lose socket 875 // options on create 876 // impl.create(true); 877 if (!usingSocks()) { 878 impl.bind(Inet4Address.ANY, 0); 879 } 880 isBound = true; 881 } 882 impl.connect(remoteAddr, timeout); 883 isConnected = true; 884 cacheLocalAddress(); 885 } catch (IOException e) { 886 impl.close(); 887 throw e; 888 } 889 } 890 } 891 892 /** 893 * Sets the Socket and its related SocketImpl state as if a successful connect() took place, 894 * without actually performing an OS connect(). 895 * 896 * @hide internal use only 897 */ 898 public void onConnect(InetAddress remoteAddress, int remotePort) { 899 isConnected = true; 900 impl.onConnect(remoteAddress, remotePort); 901 } 902 903 /** 904 * Returns whether the incoming channel of the socket has already been 905 * closed. 906 * 907 * @return {@code true} if reading from this socket is not possible anymore, 908 * {@code false} otherwise. 909 */ 910 public boolean isInputShutdown() { 911 return isInputShutdown; 912 } 913 914 /** 915 * Returns whether the outgoing channel of the socket has already been 916 * closed. 917 * 918 * @return {@code true} if writing to this socket is not possible anymore, 919 * {@code false} otherwise. 920 */ 921 public boolean isOutputShutdown() { 922 return isOutputShutdown; 923 } 924 925 /** 926 * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option. 927 */ 928 public void setReuseAddress(boolean reuse) throws SocketException { 929 checkOpenAndCreate(true); 930 impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse)); 931 } 932 933 /** 934 * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting. 935 */ 936 public boolean getReuseAddress() throws SocketException { 937 checkOpenAndCreate(true); 938 return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR); 939 } 940 941 /** 942 * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option. 943 */ 944 public void setOOBInline(boolean oobinline) throws SocketException { 945 checkOpenAndCreate(true); 946 impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline)); 947 } 948 949 /** 950 * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting. 951 */ 952 public boolean getOOBInline() throws SocketException { 953 checkOpenAndCreate(true); 954 return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE); 955 } 956 957 /** 958 * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket. 959 */ 960 public void setTrafficClass(int value) throws SocketException { 961 checkOpenAndCreate(true); 962 if (value < 0 || value > 255) { 963 throw new IllegalArgumentException("Value doesn't fit in an unsigned byte: " + value); 964 } 965 impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value)); 966 } 967 968 /** 969 * Returns this socket's {@see SocketOptions#IP_TOS} setting. 970 */ 971 public int getTrafficClass() throws SocketException { 972 checkOpenAndCreate(true); 973 return (Integer) impl.getOption(SocketOptions.IP_TOS); 974 } 975 976 /** 977 * Sends the given single byte data which is represented by the lowest octet 978 * of {@code value} as "TCP urgent data". 979 * 980 * @param value 981 * the byte of urgent data to be sent. 982 * @throws IOException 983 * if an error occurs while sending urgent data. 984 */ 985 public void sendUrgentData(int value) throws IOException { 986 impl.sendUrgentData(value); 987 } 988 989 /** 990 * Set the appropriate flags for a socket created by {@code 991 * ServerSocket.accept()}. 992 * 993 * @see ServerSocket#implAccept 994 */ 995 void accepted() throws SocketException { 996 isCreated = isBound = isConnected = true; 997 cacheLocalAddress(); 998 } 999 1000 private void cacheLocalAddress() throws SocketException { 1001 this.localAddress = IoBridge.getSocketLocalAddress(impl.fd); 1002 } 1003 1004 /** 1005 * Returns this socket's {@code SocketChannel}, if one exists. A channel is 1006 * available only if this socket wraps a channel. (That is, you can go from a 1007 * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.) 1008 * In practice, this means that the socket must have been created by 1009 * {@link java.nio.channels.ServerSocketChannel#accept} or 1010 * {@link java.nio.channels.SocketChannel#open}. 1011 */ 1012 public SocketChannel getChannel() { 1013 return null; 1014 } 1015 1016 /** 1017 * @hide internal use only 1018 */ 1019 public FileDescriptor getFileDescriptor$() { 1020 return impl.fd; 1021 } 1022 1023 /** 1024 * Sets performance preferences for connectionTime, latency and bandwidth. 1025 * 1026 * <p>This method does currently nothing. 1027 * 1028 * @param connectionTime 1029 * the value representing the importance of a short connecting 1030 * time. 1031 * @param latency 1032 * the value representing the importance of low latency. 1033 * @param bandwidth 1034 * the value representing the importance of high bandwidth. 1035 */ 1036 public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { 1037 // Our socket implementation only provide one protocol: TCP/IP, so 1038 // we do nothing for this method 1039 } 1040 } 1041