1919import com .mongodb .MongoInternalException ;
2020import com .mongodb .connection .SocketSettings ;
2121import com .mongodb .connection .SslSettings ;
22+ import jdk .net .ExtendedSocketOptions ;
2223
2324import javax .net .ssl .SSLParameters ;
2425import javax .net .ssl .SSLSocket ;
2526import java .io .IOException ;
27+ import java .lang .reflect .Method ;
2628import java .net .InetSocketAddress ;
2729import java .net .Socket ;
30+ import java .net .SocketOption ;
31+ import java .util .Arrays ;
2832
2933import static com .mongodb .internal .connection .SslHelper .enableHostNameVerification ;
3034import static com .mongodb .internal .connection .SslHelper .enableSni ;
3135import static java .util .concurrent .TimeUnit .MILLISECONDS ;
3236
3337final class SocketStreamHelper {
38+ // Keep alive options and their values for Java 11+
39+ private static final String TCP_KEEPIDLE = "TCP_KEEPIDLE" ;
40+ private static final int TCP_KEEPIDLE_DURATION = 300 ;
41+ private static final String TCP_KEEPCOUNT = "TCP_KEEPCOUNT" ;
42+ private static final int TCP_KEEPCOUNT_LIMIT = 9 ;
43+ private static final String TCP_KEEPINTERVAL = "TCP_KEEPINTERVAL" ;
44+ private static final int TCP_KEEPINTERVAL_DURATION = 10 ;
3445
3546 static void initialize (final Socket socket , final InetSocketAddress inetSocketAddress , final SocketSettings settings ,
3647 final SslSettings sslSettings ) throws IOException {
3748 socket .setTcpNoDelay (true );
3849 socket .setSoTimeout (settings .getReadTimeout (MILLISECONDS ));
3950 socket .setKeepAlive (true );
51+
52+ // Adding keep alive options for users of Java 11+. These options will be ignored for older Java versions.
53+ setExtendedSocketOptions (socket );
54+
4055 if (settings .getReceiveBufferSize () > 0 ) {
4156 socket .setReceiveBufferSize (settings .getReceiveBufferSize ());
4257 }
@@ -63,6 +78,22 @@ static void initialize(final Socket socket, final InetSocketAddress inetSocketAd
6378 socket .connect (inetSocketAddress , settings .getConnectTimeout (MILLISECONDS ));
6479 }
6580
81+ @ SuppressWarnings ("unchecked" )
82+ private static void setExtendedSocketOptions (final Socket socket ) {
83+ if (Arrays .stream (ExtendedSocketOptions .class .getDeclaredFields ()).anyMatch (f -> f .getName ().equals (TCP_KEEPCOUNT ))) {
84+ try {
85+ Method setOptionMethod = Socket .class .getMethod ("setOption" , SocketOption .class , Object .class );
86+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPCOUNT ).get (null ),
87+ TCP_KEEPCOUNT_LIMIT );
88+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPIDLE ).get (null ),
89+ TCP_KEEPIDLE_DURATION );
90+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPINTERVAL ).get (null ),
91+ TCP_KEEPINTERVAL_DURATION );
92+ } catch (Throwable t ) {
93+ }
94+ }
95+ }
96+
6697 private SocketStreamHelper () {
6798 }
6899}
0 commit comments