55 */
56 public
57 class Socket implements java.io.Closeable {
58 /**
59 * Various states of this socket.
60 */
61 private boolean created = false;
62 private boolean bound = false;
63 private boolean connected = false;
64 private boolean closed = false;
65 private Object closeLock = new Object();
66 private boolean shutIn = false;
67 private boolean shutOut = false;
68
69 /**
70 * The implementation of this Socket.
71 */
72 SocketImpl impl;
73
74 /**
75 * Are we using an older SocketImpl?
76 */
77 private boolean oldImpl = false;
78
79 /**
80 * Socket input/output streams
81 */
82 private volatile InputStream in;
83 private volatile OutputStream out;
84 private static final VarHandle IN, OUT;
85 static {
86 try {
87 MethodHandles.Lookup l = MethodHandles.lookup();
88 IN = l.findVarHandle(Socket.class, "in", InputStream.class);
89 OUT = l.findVarHandle(Socket.class, "out", OutputStream.class);
90 } catch (Exception e) {
91 throw new InternalError(e);
92 }
93 }
94
95 /**
96 * Creates an unconnected socket, with the
97 * system-default type of SocketImpl.
98 *
99 * @since 1.1
141 Proxy.Type type = p.type();
142 if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) {
143 SecurityManager security = System.getSecurityManager();
144 InetSocketAddress epoint = (InetSocketAddress) p.address();
145 if (epoint.getAddress() != null) {
146 checkAddress (epoint.getAddress(), "Socket");
147 }
148 if (security != null) {
149 if (epoint.isUnresolved())
150 epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());
151 if (epoint.isUnresolved())
152 security.checkConnect(epoint.getHostName(), epoint.getPort());
153 else
154 security.checkConnect(epoint.getAddress().getHostAddress(),
155 epoint.getPort());
156 }
157
158 // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
159 SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
160 impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
161 : new HttpConnectSocketImpl(p, delegate);
162 impl.setSocket(this);
163 } else {
164 if (p == Proxy.NO_PROXY) {
165 // create a platform or custom SocketImpl for the DIRECT case
166 SocketImplFactory factory = Socket.factory;
167 if (factory == null) {
168 impl = SocketImpl.createPlatformSocketImpl(false);
169 } else {
170 impl = factory.createSocketImpl();
171 }
172 impl.setSocket(this);
173 } else
174 throw new IllegalArgumentException("Invalid Proxy");
175 }
176 }
177
178 /**
179 * Creates an unconnected Socket with a user-specified
180 * SocketImpl.
181 *
182 * @param impl an instance of a <B>SocketImpl</B>
183 * the subclass wishes to use on the Socket.
184 *
185 * @exception SocketException if there is an error in the underlying protocol,
186 * such as a TCP error.
187 * @since 1.1
188 */
189 protected Socket(SocketImpl impl) throws SocketException {
190 this.impl = impl;
191 if (impl != null) {
192 checkOldImpl();
193 this.impl.setSocket(this);
194 }
195 }
196
197 /**
198 * Creates a stream socket and connects it to the specified port
199 * number on the named host.
200 * <p>
201 * If the specified host is {@code null} it is the equivalent of
202 * specifying the address as
203 * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
204 * In other words, it is equivalent to specifying an address of the
205 * loopback interface. </p>
206 * <p>
207 * If the application has specified a server socket factory, that
208 * factory's {@code createSocketImpl} method is called to create
209 * the actual socket implementation. Otherwise a "plain" socket is created.
210 * <p>
211 * If there is a security manager, its
212 * {@code checkConnect} method is called
213 * with the host address and {@code port}
214 * as its arguments. This could result in a SecurityException.
469
470 /**
471 * Creates the socket implementation.
472 *
473 * @param stream a {@code boolean} value : {@code true} for a TCP socket,
474 * {@code false} for UDP.
475 * @throws IOException if creation fails
476 * @since 1.4
477 */
478 void createImpl(boolean stream) throws SocketException {
479 if (impl == null)
480 setImpl();
481 try {
482 impl.create(stream);
483 created = true;
484 } catch (IOException e) {
485 throw new SocketException(e.getMessage());
486 }
487 }
488
489 private void checkOldImpl() {
490 if (impl == null)
491 return;
492 // SocketImpl.connect() is a protected method, therefore we need to use
493 // getDeclaredMethod, therefore we need permission to access the member
494
495 oldImpl = AccessController.doPrivileged
496 (new PrivilegedAction<>() {
497 public Boolean run() {
498 Class<?> clazz = impl.getClass();
499 while (true) {
500 try {
501 clazz.getDeclaredMethod("connect", SocketAddress.class, int.class);
502 return Boolean.FALSE;
503 } catch (NoSuchMethodException e) {
504 clazz = clazz.getSuperclass();
505 // java.net.SocketImpl class will always have this abstract method.
506 // If we have not found it by now in the hierarchy then it does not
507 // exist, we are an old style impl.
508 if (clazz.equals(java.net.SocketImpl.class)) {
509 return Boolean.TRUE;
510 }
511 }
512 }
513 }
514 });
515 }
516
517 void setImpl(SocketImpl si) {
518 impl = si;
519 impl.setSocket(this);
520 }
521
522 /**
523 * Sets impl to the system-default type of SocketImpl.
524 * @since 1.4
525 */
526 void setImpl() {
527 SocketImplFactory factory = Socket.factory;
528 if (factory != null) {
529 impl = factory.createSocketImpl();
530 checkOldImpl();
531 } else {
532 // create a SOCKS SocketImpl that delegates to a platform SocketImpl
533 SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
534 impl = new SocksSocketImpl(delegate);
535 }
536 if (impl != null)
537 impl.setSocket(this);
538 }
539
540 /**
541 * Get the {@code SocketImpl} attached to this socket, creating
542 * it if necessary.
543 *
544 * @return the {@code SocketImpl} attached to that ServerSocket.
545 * @throws SocketException if creation fails
546 * @since 1.4
547 */
548 SocketImpl getImpl() throws SocketException {
549 if (!created)
550 createImpl(true);
551 return impl;
552 }
553
554 /**
555 * Connects this socket to the server.
556 *
557 * @param endpoint the {@code SocketAddress}
578 * @throws IOException if an error occurs during the connection
579 * @throws SocketTimeoutException if timeout expires before connecting
580 * @throws java.nio.channels.IllegalBlockingModeException
581 * if this socket has an associated channel,
582 * and the channel is in non-blocking mode
583 * @throws IllegalArgumentException if endpoint is null or is a
584 * SocketAddress subclass not supported by this socket
585 * @since 1.4
586 * @spec JSR-51
587 */
588 public void connect(SocketAddress endpoint, int timeout) throws IOException {
589 if (endpoint == null)
590 throw new IllegalArgumentException("connect: The address can't be null");
591
592 if (timeout < 0)
593 throw new IllegalArgumentException("connect: timeout can't be negative");
594
595 if (isClosed())
596 throw new SocketException("Socket is closed");
597
598 if (!oldImpl && isConnected())
599 throw new SocketException("already connected");
600
601 if (!(endpoint instanceof InetSocketAddress))
602 throw new IllegalArgumentException("Unsupported address type");
603
604 InetSocketAddress epoint = (InetSocketAddress) endpoint;
605 InetAddress addr = epoint.getAddress ();
606 int port = epoint.getPort();
607 checkAddress(addr, "connect");
608
609 SecurityManager security = System.getSecurityManager();
610 if (security != null) {
611 if (epoint.isUnresolved())
612 security.checkConnect(epoint.getHostName(), port);
613 else
614 security.checkConnect(addr.getHostAddress(), port);
615 }
616 if (!created)
617 createImpl(true);
618 if (!oldImpl)
619 impl.connect(epoint, timeout);
620 else if (timeout == 0) {
621 if (epoint.isUnresolved())
622 impl.connect(addr.getHostName(), port);
623 else
624 impl.connect(addr, port);
625 } else
626 throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
627 connected = true;
628 /*
629 * If the socket was not bound before the connect, it is now because
630 * the kernel will have picked an ephemeral port & a local address
631 */
632 bound = true;
633 }
634
635 /**
636 * Binds the socket to a local address.
637 * <P>
638 * If the address is {@code null}, then the system will pick up
639 * an ephemeral port and a valid local address to bind the socket.
640 *
641 * @param bindpoint the {@code SocketAddress} to bind to
642 * @throws IOException if the bind operation fails, or if the socket
643 * is already bound.
644 * @throws IllegalArgumentException if bindpoint is a
645 * SocketAddress subclass not supported by this socket
646 * @throws SecurityException if a security manager exists and its
647 * {@code checkListen} method doesn't allow the bind
648 * to the local port.
649 *
650 * @since 1.4
651 * @see #isBound
652 */
653 public void bind(SocketAddress bindpoint) throws IOException {
654 if (isClosed())
655 throw new SocketException("Socket is closed");
656 if (!oldImpl && isBound())
657 throw new SocketException("Already bound");
658
659 if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
660 throw new IllegalArgumentException("Unsupported address type");
661 InetSocketAddress epoint = (InetSocketAddress) bindpoint;
662 if (epoint != null && epoint.isUnresolved())
663 throw new SocketException("Unresolved address");
664 if (epoint == null) {
665 epoint = new InetSocketAddress(0);
666 }
667 InetAddress addr = epoint.getAddress();
668 int port = epoint.getPort();
669 checkAddress (addr, "bind");
670 SecurityManager security = System.getSecurityManager();
671 if (security != null) {
672 security.checkListen(port);
673 }
674 getImpl().bind (addr, port);
675 bound = true;
676 }
677
678 private void checkAddress (InetAddress addr, String op) {
679 if (addr == null) {
680 return;
681 }
682 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
683 throw new IllegalArgumentException(op + ": invalid address type");
684 }
685 }
686
687 /**
688 * set the flags after an accept() call.
689 */
690 final void postAccept() {
691 connected = true;
692 created = true;
693 bound = true;
694 }
695
696 void setCreated() {
697 created = true;
698 }
699
700 void setBound() {
701 bound = true;
702 }
703
704 void setConnected() {
705 connected = true;
706 }
707
708 /**
709 * Returns the address to which the socket is connected.
710 * <p>
711 * If the socket was connected prior to being {@link #close closed},
712 * then this method will continue to return the connected address
713 * after the socket is closed.
714 *
715 * @return the remote IP address to which this socket is connected,
716 * or {@code null} if the socket is not connected.
717 */
718 public InetAddress getInetAddress() {
719 if (!isConnected())
720 return null;
721 try {
722 return getImpl().getInetAddress();
723 } catch (SocketException e) {
724 }
725 return null;
1653 return "Socket[addr=" + getImpl().getInetAddress() +
1654 ",port=" + getImpl().getPort() +
1655 ",localport=" + getImpl().getLocalPort() + "]";
1656 } catch (SocketException e) {
1657 }
1658 return "Socket[unconnected]";
1659 }
1660
1661 /**
1662 * Returns the connection state of the socket.
1663 * <p>
1664 * Note: Closing a socket doesn't clear its connection state, which means
1665 * this method will return {@code true} for a closed socket
1666 * (see {@link #isClosed()}) if it was successfully connected prior
1667 * to being closed.
1668 *
1669 * @return true if the socket was successfully connected to a server
1670 * @since 1.4
1671 */
1672 public boolean isConnected() {
1673 // Before 1.3 Sockets were always connected during creation
1674 return connected || oldImpl;
1675 }
1676
1677 /**
1678 * Returns the binding state of the socket.
1679 * <p>
1680 * Note: Closing a socket doesn't clear its binding state, which means
1681 * this method will return {@code true} for a closed socket
1682 * (see {@link #isClosed()}) if it was successfully bound prior
1683 * to being closed.
1684 *
1685 * @return true if the socket was successfully bound to an address
1686 * @since 1.4
1687 * @see #bind
1688 */
1689 public boolean isBound() {
1690 // Before 1.3 Sockets were always bound during creation
1691 return bound || oldImpl;
1692 }
1693
1694 /**
1695 * Returns the closed state of the socket.
1696 *
1697 * @return true if the socket has been closed
1698 * @since 1.4
1699 * @see #close
1700 */
1701 public boolean isClosed() {
1702 synchronized(closeLock) {
1703 return closed;
1704 }
1705 }
1706
1707 /**
1708 * Returns whether the read-half of the socket connection is closed.
1709 *
1710 * @return true if the input of the socket has been shutdown
1711 * @since 1.4
|
55 */
56 public
57 class Socket implements java.io.Closeable {
58 /**
59 * Various states of this socket.
60 */
61 private boolean created = false;
62 private boolean bound = false;
63 private boolean connected = false;
64 private boolean closed = false;
65 private Object closeLock = new Object();
66 private boolean shutIn = false;
67 private boolean shutOut = false;
68
69 /**
70 * The implementation of this Socket.
71 */
72 SocketImpl impl;
73
74 /**
75 * Socket input/output streams
76 */
77 private volatile InputStream in;
78 private volatile OutputStream out;
79 private static final VarHandle IN, OUT;
80 static {
81 try {
82 MethodHandles.Lookup l = MethodHandles.lookup();
83 IN = l.findVarHandle(Socket.class, "in", InputStream.class);
84 OUT = l.findVarHandle(Socket.class, "out", OutputStream.class);
85 } catch (Exception e) {
86 throw new InternalError(e);
87 }
88 }
89
90 /**
91 * Creates an unconnected socket, with the
92 * system-default type of SocketImpl.
93 *
94 * @since 1.1
136 Proxy.Type type = p.type();
137 if (type == Proxy.Type.SOCKS || type == Proxy.Type.HTTP) {
138 SecurityManager security = System.getSecurityManager();
139 InetSocketAddress epoint = (InetSocketAddress) p.address();
140 if (epoint.getAddress() != null) {
141 checkAddress (epoint.getAddress(), "Socket");
142 }
143 if (security != null) {
144 if (epoint.isUnresolved())
145 epoint = new InetSocketAddress(epoint.getHostName(), epoint.getPort());
146 if (epoint.isUnresolved())
147 security.checkConnect(epoint.getHostName(), epoint.getPort());
148 else
149 security.checkConnect(epoint.getAddress().getHostAddress(),
150 epoint.getPort());
151 }
152
153 // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
154 SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
155 impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
156 : new HttpConnectSocketImpl(p, delegate, this);
157 } else {
158 if (p == Proxy.NO_PROXY) {
159 // create a platform or custom SocketImpl for the DIRECT case
160 SocketImplFactory factory = Socket.factory;
161 if (factory == null) {
162 impl = SocketImpl.createPlatformSocketImpl(false);
163 } else {
164 impl = factory.createSocketImpl();
165 }
166 } else
167 throw new IllegalArgumentException("Invalid Proxy");
168 }
169 }
170
171 /**
172 * Creates an unconnected Socket with a user-specified
173 * SocketImpl.
174 *
175 * @param impl an instance of a <B>SocketImpl</B>
176 * the subclass wishes to use on the Socket.
177 *
178 * @exception SocketException if there is an error in the underlying protocol,
179 * such as a TCP error.
180 * @since 1.1
181 */
182 protected Socket(SocketImpl impl) throws SocketException {
183 this.impl = impl;
184 }
185
186 /**
187 * Creates a stream socket and connects it to the specified port
188 * number on the named host.
189 * <p>
190 * If the specified host is {@code null} it is the equivalent of
191 * specifying the address as
192 * {@link java.net.InetAddress#getByName InetAddress.getByName}{@code (null)}.
193 * In other words, it is equivalent to specifying an address of the
194 * loopback interface. </p>
195 * <p>
196 * If the application has specified a server socket factory, that
197 * factory's {@code createSocketImpl} method is called to create
198 * the actual socket implementation. Otherwise a "plain" socket is created.
199 * <p>
200 * If there is a security manager, its
201 * {@code checkConnect} method is called
202 * with the host address and {@code port}
203 * as its arguments. This could result in a SecurityException.
458
459 /**
460 * Creates the socket implementation.
461 *
462 * @param stream a {@code boolean} value : {@code true} for a TCP socket,
463 * {@code false} for UDP.
464 * @throws IOException if creation fails
465 * @since 1.4
466 */
467 void createImpl(boolean stream) throws SocketException {
468 if (impl == null)
469 setImpl();
470 try {
471 impl.create(stream);
472 created = true;
473 } catch (IOException e) {
474 throw new SocketException(e.getMessage());
475 }
476 }
477
478 void setImpl(SocketImpl si) {
479 impl = si;
480 }
481
482 /**
483 * Sets impl to the system-default type of SocketImpl.
484 * @since 1.4
485 */
486 void setImpl() {
487 SocketImplFactory factory = Socket.factory;
488 if (factory != null) {
489 impl = factory.createSocketImpl();
490 } else {
491 // create a SOCKS SocketImpl that delegates to a platform SocketImpl
492 SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
493 impl = new SocksSocketImpl(delegate);
494 }
495 }
496
497 /**
498 * Get the {@code SocketImpl} attached to this socket, creating
499 * it if necessary.
500 *
501 * @return the {@code SocketImpl} attached to that ServerSocket.
502 * @throws SocketException if creation fails
503 * @since 1.4
504 */
505 SocketImpl getImpl() throws SocketException {
506 if (!created)
507 createImpl(true);
508 return impl;
509 }
510
511 /**
512 * Connects this socket to the server.
513 *
514 * @param endpoint the {@code SocketAddress}
535 * @throws IOException if an error occurs during the connection
536 * @throws SocketTimeoutException if timeout expires before connecting
537 * @throws java.nio.channels.IllegalBlockingModeException
538 * if this socket has an associated channel,
539 * and the channel is in non-blocking mode
540 * @throws IllegalArgumentException if endpoint is null or is a
541 * SocketAddress subclass not supported by this socket
542 * @since 1.4
543 * @spec JSR-51
544 */
545 public void connect(SocketAddress endpoint, int timeout) throws IOException {
546 if (endpoint == null)
547 throw new IllegalArgumentException("connect: The address can't be null");
548
549 if (timeout < 0)
550 throw new IllegalArgumentException("connect: timeout can't be negative");
551
552 if (isClosed())
553 throw new SocketException("Socket is closed");
554
555 if (isConnected())
556 throw new SocketException("already connected");
557
558 if (!(endpoint instanceof InetSocketAddress))
559 throw new IllegalArgumentException("Unsupported address type");
560
561 InetSocketAddress epoint = (InetSocketAddress) endpoint;
562 InetAddress addr = epoint.getAddress ();
563 int port = epoint.getPort();
564 checkAddress(addr, "connect");
565
566 SecurityManager security = System.getSecurityManager();
567 if (security != null) {
568 if (epoint.isUnresolved())
569 security.checkConnect(epoint.getHostName(), port);
570 else
571 security.checkConnect(addr.getHostAddress(), port);
572 }
573 if (!created)
574 createImpl(true);
575
576 impl.connect(epoint, timeout);
577 connected = true;
578 /*
579 * If the socket was not bound before the connect, it is now because
580 * the kernel will have picked an ephemeral port & a local address
581 */
582 bound = true;
583 }
584
585 /**
586 * Binds the socket to a local address.
587 * <P>
588 * If the address is {@code null}, then the system will pick up
589 * an ephemeral port and a valid local address to bind the socket.
590 *
591 * @param bindpoint the {@code SocketAddress} to bind to
592 * @throws IOException if the bind operation fails, or if the socket
593 * is already bound.
594 * @throws IllegalArgumentException if bindpoint is a
595 * SocketAddress subclass not supported by this socket
596 * @throws SecurityException if a security manager exists and its
597 * {@code checkListen} method doesn't allow the bind
598 * to the local port.
599 *
600 * @since 1.4
601 * @see #isBound
602 */
603 public void bind(SocketAddress bindpoint) throws IOException {
604 if (isClosed())
605 throw new SocketException("Socket is closed");
606 if (isBound())
607 throw new SocketException("Already bound");
608
609 if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
610 throw new IllegalArgumentException("Unsupported address type");
611 InetSocketAddress epoint = (InetSocketAddress) bindpoint;
612 if (epoint != null && epoint.isUnresolved())
613 throw new SocketException("Unresolved address");
614 if (epoint == null) {
615 epoint = new InetSocketAddress(0);
616 }
617 InetAddress addr = epoint.getAddress();
618 int port = epoint.getPort();
619 checkAddress (addr, "bind");
620 SecurityManager security = System.getSecurityManager();
621 if (security != null) {
622 security.checkListen(port);
623 }
624 getImpl().bind (addr, port);
625 bound = true;
626 }
627
628 private void checkAddress (InetAddress addr, String op) {
629 if (addr == null) {
630 return;
631 }
632 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) {
633 throw new IllegalArgumentException(op + ": invalid address type");
634 }
635 }
636
637 /**
638 * set the flags after an accept() call.
639 */
640 final void postAccept() {
641 connected = true;
642 created = true;
643 bound = true;
644 // TODO impl.postAccept(); set bound / connected
645 }
646
647 /**
648 * Returns the address to which the socket is connected.
649 * <p>
650 * If the socket was connected prior to being {@link #close closed},
651 * then this method will continue to return the connected address
652 * after the socket is closed.
653 *
654 * @return the remote IP address to which this socket is connected,
655 * or {@code null} if the socket is not connected.
656 */
657 public InetAddress getInetAddress() {
658 if (!isConnected())
659 return null;
660 try {
661 return getImpl().getInetAddress();
662 } catch (SocketException e) {
663 }
664 return null;
1592 return "Socket[addr=" + getImpl().getInetAddress() +
1593 ",port=" + getImpl().getPort() +
1594 ",localport=" + getImpl().getLocalPort() + "]";
1595 } catch (SocketException e) {
1596 }
1597 return "Socket[unconnected]";
1598 }
1599
1600 /**
1601 * Returns the connection state of the socket.
1602 * <p>
1603 * Note: Closing a socket doesn't clear its connection state, which means
1604 * this method will return {@code true} for a closed socket
1605 * (see {@link #isClosed()}) if it was successfully connected prior
1606 * to being closed.
1607 *
1608 * @return true if the socket was successfully connected to a server
1609 * @since 1.4
1610 */
1611 public boolean isConnected() {
1612 return connected;
1613 }
1614
1615 /**
1616 * Returns the binding state of the socket.
1617 * <p>
1618 * Note: Closing a socket doesn't clear its binding state, which means
1619 * this method will return {@code true} for a closed socket
1620 * (see {@link #isClosed()}) if it was successfully bound prior
1621 * to being closed.
1622 *
1623 * @return true if the socket was successfully bound to an address
1624 * @since 1.4
1625 * @see #bind
1626 */
1627 public boolean isBound() {
1628 return bound;
1629 }
1630
1631 /**
1632 * Returns the closed state of the socket.
1633 *
1634 * @return true if the socket has been closed
1635 * @since 1.4
1636 * @see #close
1637 */
1638 public boolean isClosed() {
1639 synchronized(closeLock) {
1640 return closed;
1641 }
1642 }
1643
1644 /**
1645 * Returns whether the read-half of the socket connection is closed.
1646 *
1647 * @return true if the input of the socket has been shutdown
1648 * @since 1.4
|