src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
branchniosocketimpl-branch
changeset 57281 c08d024d6bf9
parent 57274 07b6be5d9150
child 57294 c1126b592df9
equal deleted inserted replaced
57280:a458758d1a63 57281:c08d024d6bf9
   520             }
   520             }
   521         }
   521         }
   522     }
   522     }
   523 
   523 
   524     /**
   524     /**
   525      * Waits for a connection attempt to finish with a timeout.
   525      * Waits for a connection attempt to finish with a timeout
   526      * @throws SocketTimeoutException if the connect timeout elapses
   526      * @throws SocketTimeoutException if the connect timeout elapses
   527      */
   527      */
   528     private boolean timedFinishConnect(FileDescriptor fd, int millis) throws IOException {
   528     private void timedFinishConnect(FileDescriptor fd, int millis) throws IOException {
   529         long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
   529         long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
   530         long remainingNanos = nanos;
   530         long remainingNanos = nanos;
   531         long startNanos = System.nanoTime();
   531         long startNanos = System.nanoTime();
   532         boolean connected;
   532         boolean polled;
   533         do {
   533         do {
   534             park(fd, Net.POLLOUT, remainingNanos);
   534             park(fd, Net.POLLOUT, remainingNanos);
   535             connected = Net.pollConnectNow(fd);
   535             polled = Net.pollConnectNow(fd);
   536             if (!connected) {
   536             if (!polled) {
   537                 remainingNanos = nanos - (System.nanoTime() - startNanos);
   537                 remainingNanos = nanos - (System.nanoTime() - startNanos);
   538                 if (remainingNanos <= 0) {
   538                 if (remainingNanos <= 0) {
   539                     throw new SocketTimeoutException("Connect timed out");
   539                     throw new SocketTimeoutException("Connect timed out");
   540                 }
   540                 }
   541             }
   541             }
   542         } while (!connected && isOpen());
   542         } while (!polled && isOpen());
   543         return connected;
       
   544     }
   543     }
   545 
   544 
   546     /**
   545     /**
   547      * Attempts to establish a connection to the given socket address with a
   546      * Attempts to establish a connection to the given socket address with a
   548      * timeout. Closes the socket if connection cannot be established.
   547      * timeout. Closes the socket if connection cannot be established.
   549      * @throws IllegalArgumentException if the address is not an InetSocketAddress
   548      * @throws IOException if the address is not a resolved InetSocketAdress or
   550      * @throws UnknownHostException if the InetSocketAddress is not resolved
   549      *         the connection cannot be established
   551      * @throws IOException if the connection cannot be established
       
   552      */
   550      */
   553     private void implConnect(SocketAddress remote, int millis) throws IOException {
   551     private void implConnect(SocketAddress remote, int millis) throws IOException {
       
   552         // SocketImpl connect only specifies IOException
   554         if (!(remote instanceof InetSocketAddress))
   553         if (!(remote instanceof InetSocketAddress))
   555             throw new IllegalArgumentException("Unsupported address type");
   554             throw new IOException("Unsupported address type");
   556         InetSocketAddress isa = (InetSocketAddress) remote;
   555         InetSocketAddress isa = (InetSocketAddress) remote;
   557         if (isa.isUnresolved()) {
   556         if (isa.isUnresolved()) {
   558             throw new UnknownHostException(isa.getHostName());
   557             throw new UnknownHostException(isa.getHostName());
   559         }
   558         }
   560 
   559 
   570                 boolean connected = false;
   569                 boolean connected = false;
   571                 FileDescriptor fd = beginConnect(address, port);
   570                 FileDescriptor fd = beginConnect(address, port);
   572                 try {
   571                 try {
   573                     configureNonBlockingIfNeeded(fd, millis);
   572                     configureNonBlockingIfNeeded(fd, millis);
   574                     int n = Net.connect(fd, address, port);
   573                     int n = Net.connect(fd, address, port);
   575                     if (n > 0 && isOpen()) {
   574                     if (isOpen()) {
   576                         connected = true;
   575                         if (n > 0) {
   577                     } else if (IOStatus.okayToRetry(n) && isOpen()) {
   576                             // connection established
   578                         if (millis > 0) {
   577                             connected = true;
   579                             // finish connect with timeout
   578                         } else if (IOStatus.okayToRetry(n)) {
   580                             connected = timedFinishConnect(fd, millis);
   579                             // not established or interrupted
   581                         } else {
   580                             if (millis > 0) {
   582                             // finish connect, no timeout
   581                                 // finish connect with timeout
   583                             do {
   582                                 timedFinishConnect(fd, millis);
   584                                 park(fd, Net.POLLOUT);
   583                             } else {
   585                                 connected = Net.pollConnectNow(fd);
   584                                 // finish connect, no timeout
   586                             } while (!connected && isOpen());
   585                                 boolean polled;
       
   586                                 do {
       
   587                                     park(fd, Net.POLLOUT);
       
   588                                     polled = Net.pollConnectNow(fd);
       
   589                                 } while (!polled && isOpen());
       
   590                             }
       
   591                             connected = isOpen();
   587                         }
   592                         }
   588                     }
   593                     }
   589                 } finally {
   594                 } finally {
   590                     endConnect(connected);
   595                     endConnect(connected);
   591                 }
   596                 }
   884         // restore interrupt status
   889         // restore interrupt status
   885         if (interrupted)
   890         if (interrupted)
   886             Thread.currentThread().interrupt();
   891             Thread.currentThread().interrupt();
   887     }
   892     }
   888 
   893 
       
   894     // the socket options supported by client and server sockets
       
   895     private static volatile Set<SocketOption<?>> clientSocketOptions;
       
   896     private static volatile Set<SocketOption<?>> serverSocketOptions;
       
   897 
   889     @Override
   898     @Override
   890     protected Set<SocketOption<?>> supportedOptions() {
   899     protected Set<SocketOption<?>> supportedOptions() {
   891         Set<SocketOption<?>> options = new HashSet<>();
   900         Set<SocketOption<?>> options = (server) ? serverSocketOptions : clientSocketOptions;
   892         options.addAll(super.supportedOptions());
   901         if (options == null) {
   893         if (server) {
   902             options = new HashSet<>();
   894             options.addAll(ExtendedSocketOptions.serverSocketOptions());
   903             options.add(StandardSocketOptions.SO_RCVBUF);
   895         } else {
   904             options.add(StandardSocketOptions.SO_REUSEADDR);
   896             options.addAll(ExtendedSocketOptions.clientSocketOptions());
   905             if (server) {
   897         }
   906                 // IP_TOS added for server socket to maintain compatibility
   898         if (Net.isReusePortAvailable())
   907                 options.add(StandardSocketOptions.IP_TOS);
   899             options.add(StandardSocketOptions.SO_REUSEPORT);
   908                 options.addAll(ExtendedSocketOptions.serverSocketOptions());
   900         return Collections.unmodifiableSet(options);
   909             } else {
       
   910                 options.add(StandardSocketOptions.IP_TOS);
       
   911                 options.add(StandardSocketOptions.SO_KEEPALIVE);
       
   912                 options.add(StandardSocketOptions.SO_SNDBUF);
       
   913                 options.add(StandardSocketOptions.SO_LINGER);
       
   914                 options.add(StandardSocketOptions.TCP_NODELAY);
       
   915                 options.addAll(ExtendedSocketOptions.clientSocketOptions());
       
   916             }
       
   917             if (Net.isReusePortAvailable())
       
   918                 options.add(StandardSocketOptions.SO_REUSEPORT);
       
   919             options = Collections.unmodifiableSet(options);
       
   920             if (server) {
       
   921                 serverSocketOptions = options;
       
   922             } else {
       
   923                 clientSocketOptions = options;
       
   924             }
       
   925         }
       
   926         return options;
   901     }
   927     }
   902 
   928 
   903     @Override
   929     @Override
   904     protected <T> void setOption(SocketOption<T> opt, T value) throws IOException {
   930     protected <T> void setOption(SocketOption<T> opt, T value) throws IOException {
   905         if (!supportedOptions().contains(opt))
   931         if (!supportedOptions().contains(opt))