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 = Inet6Address.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 */ Socket()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 */ Socket(Proxy proxy)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 */ tryAllAddresses(String dstName, int dstPort, InetAddress localAddress, int localPort, boolean streaming)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 */ Socket(String dstName, int dstPort)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 */ Socket(String dstName, int dstPort, InetAddress localAddress, int localPort)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 Socket(String hostName, int port, boolean streaming)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 using a wildcard address. 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 */ Socket(InetAddress dstAddress, int dstPort)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}. 232 * 233 * <p>On the local endpoint the socket is bound to the given address {@code localAddress} on 234 * port {@code localPort}. If {@code localAddress} is {@code null} the socket will be bound to a 235 * wildcard address. 236 * 237 * @param dstAddress 238 * the target host address to connect to. 239 * @param dstPort 240 * the port on the target host to connect to. 241 * @param localAddress 242 * the address on the local host to bind to, or null. 243 * @param localPort 244 * the port on the local host to bind to. 245 * @throws IOException 246 * if an error occurs while creating the socket. 247 */ Socket(InetAddress dstAddress, int dstPort, InetAddress localAddress, int localPort)248 public Socket(InetAddress dstAddress, int dstPort, 249 InetAddress localAddress, int localPort) throws IOException { 250 this(); 251 checkDestination(dstAddress, dstPort); 252 startupSocket(dstAddress, dstPort, localAddress, localPort, true); 253 } 254 255 /** 256 * Creates a new streaming or datagram socket connected to the target host 257 * specified by the parameters {@code addr} and {@code port}. The socket is 258 * bound to any available port on the local host using a wildcard address. 259 * 260 * @param addr 261 * the Internet address to connect to. 262 * @param port 263 * the port on the target host to connect to. 264 * @param streaming 265 * if {@code true} a streaming socket is returned, a datagram 266 * socket otherwise. 267 * @throws IOException 268 * if an error occurs while creating the socket. 269 * @deprecated Use {@code Socket(InetAddress, int)} instead of this for 270 * streaming sockets or an appropriate constructor of {@code 271 * DatagramSocket} for UDP transport. 272 */ 273 @Deprecated Socket(InetAddress addr, int port, boolean streaming)274 public Socket(InetAddress addr, int port, boolean streaming) throws IOException { 275 this(); 276 checkDestination(addr, port); 277 startupSocket(addr, port, null, 0, streaming); 278 } 279 280 /** 281 * Creates an unconnected socket with the given socket implementation. 282 * 283 * @param impl 284 * the socket implementation to be used. 285 * @throws SocketException 286 * if an error occurs while creating the socket. 287 */ Socket(SocketImpl impl)288 protected Socket(SocketImpl impl) throws SocketException { 289 this.impl = impl; 290 this.proxy = null; 291 } 292 293 /** 294 * Checks whether the connection destination satisfies the security policy 295 * and the validity of the port range. 296 * 297 * @param destAddr 298 * the destination host address. 299 * @param dstPort 300 * the port on the destination host. 301 */ checkDestination(InetAddress destAddr, int dstPort)302 private void checkDestination(InetAddress destAddr, int dstPort) { 303 if (dstPort < 0 || dstPort > 65535) { 304 throw new IllegalArgumentException("Port out of range: " + dstPort); 305 } 306 } 307 308 /** 309 * Closes the socket. It is not possible to reconnect or rebind to this 310 * socket thereafter which means a new socket instance has to be created. 311 * 312 * @throws IOException 313 * if an error occurs while closing the socket. 314 */ close()315 public synchronized void close() throws IOException { 316 isClosed = true; 317 isConnected = false; 318 // RI compatibility: the RI returns the any address (but the original local port) after 319 // close. 320 localAddress = Inet6Address.ANY; 321 impl.close(); 322 } 323 324 /** 325 * Sets the Socket and its related SocketImpl state as if a successful close() took place, 326 * without actually performing an OS close(). 327 * 328 * @hide used in java.nio 329 */ onClose()330 public void onClose() { 331 isClosed = true; 332 isConnected = false; 333 // RI compatibility: the RI returns the any address (but the original local port) after 334 // close. 335 localAddress = Inet6Address.ANY; 336 impl.onClose(); 337 } 338 339 /** 340 * Returns the IP address of the target host this socket is connected to, or null if this 341 * socket is not yet connected. 342 */ getInetAddress()343 public InetAddress getInetAddress() { 344 if (!isConnected()) { 345 return null; 346 } 347 return impl.getInetAddress(); 348 } 349 350 /** 351 * Returns an input stream to read data from this socket. If the socket has an associated 352 * {@link SocketChannel} and that channel is in non-blocking mode then reads from the 353 * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}. 354 * 355 * @return the byte-oriented input stream. 356 * @throws IOException 357 * if an error occurs while creating the input stream or the 358 * socket is in an invalid state. 359 */ getInputStream()360 public InputStream getInputStream() throws IOException { 361 checkOpenAndCreate(false); 362 if (isInputShutdown()) { 363 throw new SocketException("Socket input is shutdown"); 364 } 365 return impl.getInputStream(); 366 } 367 368 /** 369 * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting. 370 */ getKeepAlive()371 public boolean getKeepAlive() throws SocketException { 372 checkOpenAndCreate(true); 373 return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE); 374 } 375 376 /** 377 * Returns the local IP address this socket is bound to, or an address for which 378 * {@link InetAddress#isAnyLocalAddress()} returns true if the socket is closed or unbound. 379 */ getLocalAddress()380 public InetAddress getLocalAddress() { 381 return localAddress; 382 } 383 384 /** 385 * Returns the local port this socket is bound to, or -1 if the socket is unbound. If the socket 386 * has been closed this method will still return the local port the socket was bound to. 387 */ getLocalPort()388 public int getLocalPort() { 389 if (!isBound()) { 390 return -1; 391 } 392 return impl.getLocalPort(); 393 } 394 395 /** 396 * Returns an output stream to write data into this socket. If the socket has an associated 397 * {@link SocketChannel} and that channel is in non-blocking mode then writes to the 398 * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}. 399 * 400 * @return the byte-oriented output stream. 401 * @throws IOException 402 * if an error occurs while creating the output stream or the 403 * socket is in an invalid state. 404 */ getOutputStream()405 public OutputStream getOutputStream() throws IOException { 406 checkOpenAndCreate(false); 407 if (isOutputShutdown()) { 408 throw new SocketException("Socket output is shutdown"); 409 } 410 return impl.getOutputStream(); 411 } 412 413 /** 414 * Returns the port number of the target host this socket is connected to, or 0 if this socket 415 * is not yet connected. 416 */ getPort()417 public int getPort() { 418 if (!isConnected()) { 419 return 0; 420 } 421 return impl.getPort(); 422 } 423 424 /** 425 * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1 426 * for no linger (i.e. {@code close} will return immediately). 427 */ getSoLinger()428 public int getSoLinger() throws SocketException { 429 checkOpenAndCreate(true); 430 // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation. 431 Object value = impl.getOption(SocketOptions.SO_LINGER); 432 if (value instanceof Integer) { 433 return (Integer) value; 434 } else { 435 return -1; 436 } 437 } 438 439 /** 440 * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}. 441 */ getReceiveBufferSize()442 public synchronized int getReceiveBufferSize() throws SocketException { 443 checkOpenAndCreate(true); 444 return (Integer) impl.getOption(SocketOptions.SO_RCVBUF); 445 } 446 447 /** 448 * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}. 449 */ getSendBufferSize()450 public synchronized int getSendBufferSize() throws SocketException { 451 checkOpenAndCreate(true); 452 return (Integer) impl.getOption(SocketOptions.SO_SNDBUF); 453 } 454 455 /** 456 * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}. 457 */ getSoTimeout()458 public synchronized int getSoTimeout() throws SocketException { 459 checkOpenAndCreate(true); 460 return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT); 461 } 462 463 /** 464 * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting. 465 */ getTcpNoDelay()466 public boolean getTcpNoDelay() throws SocketException { 467 checkOpenAndCreate(true); 468 return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY); 469 } 470 471 /** 472 * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option. 473 */ setKeepAlive(boolean keepAlive)474 public void setKeepAlive(boolean keepAlive) throws SocketException { 475 if (impl != null) { 476 checkOpenAndCreate(true); 477 impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive)); 478 } 479 } 480 481 /** 482 * Sets the internal factory for creating socket implementations. This may 483 * only be executed once during the lifetime of the application. 484 * 485 * @param fac 486 * the socket implementation factory to be set. 487 * @throws IOException 488 * if the factory has been already set. 489 */ setSocketImplFactory(SocketImplFactory fac)490 public static synchronized void setSocketImplFactory(SocketImplFactory fac) 491 throws IOException { 492 if (factory != null) { 493 throw new SocketException("Factory already set"); 494 } 495 factory = fac; 496 } 497 498 /** 499 * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}. 500 */ setSendBufferSize(int size)501 public synchronized void setSendBufferSize(int size) throws SocketException { 502 checkOpenAndCreate(true); 503 if (size < 1) { 504 throw new IllegalArgumentException("size < 1"); 505 } 506 impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size)); 507 } 508 509 /** 510 * Sets this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}. 511 */ setReceiveBufferSize(int size)512 public synchronized void setReceiveBufferSize(int size) throws SocketException { 513 checkOpenAndCreate(true); 514 if (size < 1) { 515 throw new IllegalArgumentException("size < 1"); 516 } 517 impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size)); 518 } 519 520 /** 521 * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds. 522 * If {@code on} is false, {@code timeout} is irrelevant. 523 */ setSoLinger(boolean on, int timeout)524 public void setSoLinger(boolean on, int timeout) throws SocketException { 525 checkOpenAndCreate(true); 526 // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation. 527 if (on && timeout < 0) { 528 throw new IllegalArgumentException("timeout < 0"); 529 } 530 if (on) { 531 impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout)); 532 } else { 533 impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE); 534 } 535 } 536 537 /** 538 * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds. 539 * Use 0 for no timeout. 540 * To take effect, this option must be set before the blocking method was called. 541 */ setSoTimeout(int timeout)542 public synchronized void setSoTimeout(int timeout) throws SocketException { 543 checkOpenAndCreate(true); 544 if (timeout < 0) { 545 throw new IllegalArgumentException("timeout < 0"); 546 } 547 impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout)); 548 } 549 550 /** 551 * Sets this socket's {@link SocketOptions#TCP_NODELAY} option. 552 */ setTcpNoDelay(boolean on)553 public void setTcpNoDelay(boolean on) throws SocketException { 554 checkOpenAndCreate(true); 555 impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on)); 556 } 557 558 /** 559 * Creates a stream socket, binds it to the nominated local address/port, 560 * then connects it to the nominated destination address/port. 561 * 562 * @param dstAddress 563 * the destination host address. 564 * @param dstPort 565 * the port on the destination host. 566 * @param localAddress 567 * the address on the local machine to bind. 568 * @param localPort 569 * the port on the local machine to bind. 570 * @throws IOException 571 * thrown if an error occurs during the bind or connect 572 * operations. 573 */ startupSocket(InetAddress dstAddress, int dstPort, InetAddress localAddress, int localPort, boolean streaming)574 private void startupSocket(InetAddress dstAddress, int dstPort, 575 InetAddress localAddress, int localPort, boolean streaming) 576 throws IOException { 577 578 if (localPort < 0 || localPort > 65535) { 579 throw new IllegalArgumentException("Local port out of range: " + localPort); 580 } 581 582 InetAddress addr = localAddress == null ? Inet6Address.ANY : localAddress; 583 synchronized (this) { 584 impl.create(streaming); 585 isCreated = true; 586 try { 587 if (!streaming || !usingSocks()) { 588 impl.bind(addr, localPort); 589 } 590 isBound = true; 591 cacheLocalAddress(); 592 impl.connect(dstAddress, dstPort); 593 isConnected = true; 594 cacheLocalAddress(); 595 } catch (IOException e) { 596 impl.close(); 597 throw e; 598 } 599 } 600 } 601 usingSocks()602 private boolean usingSocks() { 603 return proxy != null && proxy.type() == Proxy.Type.SOCKS; 604 } 605 606 /** 607 * Returns a {@code String} containing a concise, human-readable description of the 608 * socket. 609 * 610 * @return the textual representation of this socket. 611 */ 612 @Override toString()613 public String toString() { 614 if (!isConnected()) { 615 return "Socket[unconnected]"; 616 } 617 return impl.toString(); 618 } 619 620 /** 621 * Closes the input stream of this socket. Any further data sent to this 622 * socket will be discarded. Reading from this socket after this method has 623 * been called will return the value {@code EOF}. 624 * 625 * @throws IOException 626 * if an error occurs while closing the socket input stream. 627 * @throws SocketException 628 * if the input stream is already closed. 629 */ shutdownInput()630 public void shutdownInput() throws IOException { 631 if (isInputShutdown()) { 632 throw new SocketException("Socket input is shutdown"); 633 } 634 checkOpenAndCreate(false); 635 impl.shutdownInput(); 636 isInputShutdown = true; 637 } 638 639 /** 640 * Closes the output stream of this socket. All buffered data will be sent 641 * followed by the termination sequence. Writing to the closed output stream 642 * will cause an {@code IOException}. 643 * 644 * @throws IOException 645 * if an error occurs while closing the socket output stream. 646 * @throws SocketException 647 * if the output stream is already closed. 648 */ shutdownOutput()649 public void shutdownOutput() throws IOException { 650 if (isOutputShutdown()) { 651 throw new SocketException("Socket output is shutdown"); 652 } 653 checkOpenAndCreate(false); 654 impl.shutdownOutput(); 655 isOutputShutdown = true; 656 } 657 658 /** 659 * Checks whether the socket is closed, and throws an exception. Otherwise 660 * creates the underlying SocketImpl. 661 * 662 * @throws SocketException 663 * if the socket is closed. 664 */ checkOpenAndCreate(boolean create)665 private void checkOpenAndCreate(boolean create) throws SocketException { 666 if (isClosed()) { 667 throw new SocketException("Socket is closed"); 668 } 669 if (!create) { 670 if (!isConnected()) { 671 throw new SocketException("Socket is not connected"); 672 // a connected socket must be created 673 } 674 675 /* 676 * return directly to fix a possible bug, if !create, should return 677 * here 678 */ 679 return; 680 } 681 if (isCreated) { 682 return; 683 } 684 synchronized (this) { 685 if (isCreated) { 686 return; 687 } 688 try { 689 impl.create(true); 690 } catch (SocketException e) { 691 throw e; 692 } catch (IOException e) { 693 throw new SocketException(e.toString()); 694 } 695 isCreated = true; 696 } 697 } 698 699 /** 700 * Returns the local address and port of this socket as a SocketAddress or null if the socket 701 * has never been bound. If the socket is closed but has previously been bound then an address 702 * for which {@link InetAddress#isAnyLocalAddress()} returns true will be returned with the 703 * previously-bound port. This is useful on multihomed hosts. 704 */ getLocalSocketAddress()705 public SocketAddress getLocalSocketAddress() { 706 if (!isBound()) { 707 return null; 708 } 709 return new InetSocketAddress(getLocalAddress(), getLocalPort()); 710 } 711 712 /** 713 * Returns the remote address and port of this socket as a {@code 714 * SocketAddress} or null if the socket is not connected. 715 * 716 * @return the remote socket address and port. 717 */ getRemoteSocketAddress()718 public SocketAddress getRemoteSocketAddress() { 719 if (!isConnected()) { 720 return null; 721 } 722 return new InetSocketAddress(getInetAddress(), getPort()); 723 } 724 725 /** 726 * Returns whether this socket is bound to a local address and port. 727 * 728 * @return {@code true} if the socket is bound to a local address, {@code 729 * false} otherwise. 730 */ isBound()731 public boolean isBound() { 732 return isBound; 733 } 734 735 /** 736 * Returns whether this socket is connected to a remote host. 737 * 738 * @return {@code true} if the socket is connected, {@code false} otherwise. 739 */ isConnected()740 public boolean isConnected() { 741 return isConnected; 742 } 743 744 /** 745 * Returns whether this socket is closed. 746 * 747 * @return {@code true} if the socket is closed, {@code false} otherwise. 748 */ isClosed()749 public boolean isClosed() { 750 return isClosed; 751 } 752 753 /** 754 * Binds this socket to the given local host address and port specified by 755 * the SocketAddress {@code localAddr}. If {@code localAddr} is set to 756 * {@code null}, this socket will be bound to an available local address on 757 * any free port. 758 * 759 * @param localAddr 760 * the specific address and port on the local machine to bind to. 761 * @throws IllegalArgumentException 762 * if the given SocketAddress is invalid or not supported. 763 * @throws IOException 764 * if the socket is already bound or an error occurs while 765 * binding. 766 */ bind(SocketAddress localAddr)767 public void bind(SocketAddress localAddr) throws IOException { 768 checkOpenAndCreate(true); 769 if (isBound()) { 770 throw new BindException("Socket is already bound"); 771 } 772 773 int port; 774 InetAddress addr; 775 if (localAddr == null) { 776 port = 0; 777 addr = Inet6Address.ANY; 778 } else { 779 if (!(localAddr instanceof InetSocketAddress)) { 780 throw new IllegalArgumentException("Local address not an InetSocketAddress: " + 781 localAddr.getClass()); 782 } 783 InetSocketAddress inetAddr = (InetSocketAddress) localAddr; 784 if ((addr = inetAddr.getAddress()) == null) { 785 throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName()); 786 } 787 port = inetAddr.getPort(); 788 } 789 790 synchronized (this) { 791 try { 792 impl.bind(addr, port); 793 isBound = true; 794 cacheLocalAddress(); 795 } catch (IOException e) { 796 impl.close(); 797 throw e; 798 } 799 } 800 } 801 802 /** 803 * Sets the Socket and its related SocketImpl state as if a successful bind() took place, 804 * without actually performing an OS bind(). 805 * 806 * @hide used in java.nio 807 */ onBind(InetAddress localAddress, int localPort)808 public void onBind(InetAddress localAddress, int localPort) { 809 isBound = true; 810 this.localAddress = localAddress; 811 impl.onBind(localAddress, localPort); 812 } 813 814 /** 815 * Connects this socket to the given remote host address and port specified 816 * by the SocketAddress {@code remoteAddr}. 817 * 818 * @param remoteAddr 819 * the address and port of the remote host to connect to. 820 * @throws IllegalArgumentException 821 * if the given SocketAddress is invalid or not supported. 822 * @throws IOException 823 * if the socket is already connected or an error occurs while 824 * connecting. 825 */ connect(SocketAddress remoteAddr)826 public void connect(SocketAddress remoteAddr) throws IOException { 827 connect(remoteAddr, 0); 828 } 829 830 /** 831 * Connects this socket to the given remote host address and port specified 832 * by the SocketAddress {@code remoteAddr} with the specified timeout. The 833 * connecting method will block until the connection is established or an 834 * error occurred. 835 * 836 * @param remoteAddr 837 * the address and port of the remote host to connect to. 838 * @param timeout 839 * the timeout value in milliseconds or {@code 0} for an infinite 840 * timeout. 841 * @throws IllegalArgumentException 842 * if the given SocketAddress is invalid or not supported or the 843 * timeout value is negative. 844 * @throws IOException 845 * if the socket is already connected or an error occurs while 846 * connecting. 847 */ connect(SocketAddress remoteAddr, int timeout)848 public void connect(SocketAddress remoteAddr, int timeout) throws IOException { 849 checkOpenAndCreate(true); 850 if (timeout < 0) { 851 throw new IllegalArgumentException("timeout < 0"); 852 } 853 if (isConnected()) { 854 throw new SocketException("Already connected"); 855 } 856 if (remoteAddr == null) { 857 throw new IllegalArgumentException("remoteAddr == null"); 858 } 859 860 if (!(remoteAddr instanceof InetSocketAddress)) { 861 throw new IllegalArgumentException("Remote address not an InetSocketAddress: " + 862 remoteAddr.getClass()); 863 } 864 InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr; 865 InetAddress addr; 866 if ((addr = inetAddr.getAddress()) == null) { 867 throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName()); 868 } 869 int port = inetAddr.getPort(); 870 871 checkDestination(addr, port); 872 synchronized (connectLock) { 873 try { 874 if (!isBound()) { 875 // socket already created at this point by earlier call or 876 // checkOpenAndCreate this caused us to lose socket 877 // options on create 878 // impl.create(true); 879 if (!usingSocks()) { 880 impl.bind(Inet6Address.ANY, 0); 881 } 882 isBound = true; 883 } 884 impl.connect(remoteAddr, timeout); 885 isConnected = true; 886 cacheLocalAddress(); 887 } catch (IOException e) { 888 impl.close(); 889 throw e; 890 } 891 } 892 } 893 894 /** 895 * Sets the Socket and its related SocketImpl state as if a successful connect() took place, 896 * without actually performing an OS connect(). 897 * 898 * @hide internal use only 899 */ onConnect(InetAddress remoteAddress, int remotePort)900 public void onConnect(InetAddress remoteAddress, int remotePort) { 901 isConnected = true; 902 impl.onConnect(remoteAddress, remotePort); 903 } 904 905 /** 906 * Returns whether the incoming channel of the socket has already been 907 * closed. 908 * 909 * @return {@code true} if reading from this socket is not possible anymore, 910 * {@code false} otherwise. 911 */ isInputShutdown()912 public boolean isInputShutdown() { 913 return isInputShutdown; 914 } 915 916 /** 917 * Returns whether the outgoing channel of the socket has already been 918 * closed. 919 * 920 * @return {@code true} if writing to this socket is not possible anymore, 921 * {@code false} otherwise. 922 */ isOutputShutdown()923 public boolean isOutputShutdown() { 924 return isOutputShutdown; 925 } 926 927 /** 928 * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option. 929 */ setReuseAddress(boolean reuse)930 public void setReuseAddress(boolean reuse) throws SocketException { 931 checkOpenAndCreate(true); 932 impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse)); 933 } 934 935 /** 936 * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting. 937 */ getReuseAddress()938 public boolean getReuseAddress() throws SocketException { 939 checkOpenAndCreate(true); 940 return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR); 941 } 942 943 /** 944 * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option. 945 */ setOOBInline(boolean oobinline)946 public void setOOBInline(boolean oobinline) throws SocketException { 947 checkOpenAndCreate(true); 948 impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline)); 949 } 950 951 /** 952 * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting. 953 */ getOOBInline()954 public boolean getOOBInline() throws SocketException { 955 checkOpenAndCreate(true); 956 return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE); 957 } 958 959 /** 960 * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket. 961 */ setTrafficClass(int value)962 public void setTrafficClass(int value) throws SocketException { 963 checkOpenAndCreate(true); 964 if (value < 0 || value > 255) { 965 throw new IllegalArgumentException("Value doesn't fit in an unsigned byte: " + value); 966 } 967 impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value)); 968 } 969 970 /** 971 * Returns this socket's {@see SocketOptions#IP_TOS} setting. 972 */ getTrafficClass()973 public int getTrafficClass() throws SocketException { 974 checkOpenAndCreate(true); 975 return (Integer) impl.getOption(SocketOptions.IP_TOS); 976 } 977 978 /** 979 * Sends the given single byte data which is represented by the lowest octet 980 * of {@code value} as "TCP urgent data". 981 * 982 * @param value 983 * the byte of urgent data to be sent. 984 * @throws IOException 985 * if an error occurs while sending urgent data. 986 */ sendUrgentData(int value)987 public void sendUrgentData(int value) throws IOException { 988 impl.sendUrgentData(value); 989 } 990 991 /** 992 * Set the appropriate flags for a socket created by {@code 993 * ServerSocket.accept()}. 994 * 995 * @see ServerSocket#implAccept 996 */ accepted()997 void accepted() throws SocketException { 998 isCreated = isBound = isConnected = true; 999 cacheLocalAddress(); 1000 } 1001 cacheLocalAddress()1002 private void cacheLocalAddress() throws SocketException { 1003 this.localAddress = IoBridge.getSocketLocalAddress(impl.fd); 1004 } 1005 1006 /** 1007 * Returns this socket's {@code SocketChannel}, if one exists. A channel is 1008 * available only if this socket wraps a channel. (That is, you can go from a 1009 * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.) 1010 * In practice, this means that the socket must have been created by 1011 * {@link java.nio.channels.ServerSocketChannel#accept} or 1012 * {@link java.nio.channels.SocketChannel#open}. 1013 */ getChannel()1014 public SocketChannel getChannel() { 1015 return null; 1016 } 1017 1018 /** 1019 * @hide internal use only 1020 */ getFileDescriptor$()1021 public FileDescriptor getFileDescriptor$() { 1022 return impl.fd; 1023 } 1024 1025 /** 1026 * Sets performance preferences for connectionTime, latency and bandwidth. 1027 * 1028 * <p>This method does currently nothing. 1029 * 1030 * @param connectionTime 1031 * the value representing the importance of a short connecting 1032 * time. 1033 * @param latency 1034 * the value representing the importance of low latency. 1035 * @param bandwidth 1036 * the value representing the importance of high bandwidth. 1037 */ setPerformancePreferences(int connectionTime, int latency, int bandwidth)1038 public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { 1039 // Our socket implementation only provide one protocol: TCP/IP, so 1040 // we do nothing for this method 1041 } 1042 } 1043