2017-08-03 98 views
0

我写的SSLSocketFactory的一个简单的HTTP服务器,这里是我的Java代码:SSL握手:为什么服务器端在服务器端ChangeCipherSpec和Finished之间等待100 + ms?

public static void main(String[] args) throws Exception { 
     KeyStore ks = KeyStore.getInstance("PKCS12"); 
     ks.load(TestEcho.class.getResourceAsStream("/localhost.pfx"), 
       "****".toCharArray()); 
     KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
     kmf.init(ks, "****".toCharArray()); 
     SSLContext sslc = SSLContext.getInstance("TLS"); 
     sslc.init(kmf.getKeyManagers(), null, null); 

     // try (ServerSocket server = new ServerSocket(4443)) { 
     try (ServerSocket server = sslc.getServerSocketFactory().createServerSocket(4443)) { 
      while (true) { 
       Socket socket = server.accept(); 
       // ((SSLSocket) socket).getSession(); 
       socket.getInputStream().read(); 
       socket.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 2\r\nConnection: close\r\n\r\nok".getBytes()); 
       socket.getOutputStream().flush(); 
      } 
     } 
} 

但性能比Tomcat的Http11Protocol(生物)低得多。我捕获了TCP转储,并在服务器端ChangeCipherSpec和Finished之间找到了100 + ms的差距。但是当我连接到Tomcat时,没有这种差距。

我上面的代码的TCP转储是:

[127.0.0.1:1962 Connected at 00:58:21.718] 
[127.0.0.1:1962 Sent at 00:58:21.718] // ClientHello 
0000:0000 16 03 03 00 C3 01 00 00-BF 03 03 59 82 04 AD 44 ...........Y...D 
... 
0000:00C0 02 03 02 01 02 02 01 01       ........   
[127.0.0.1:1962 Received at 00:58:21.781] // ServerHello & Certificate & ServerHelloDone 
0000:0000 16 03 03 0B EB 02 00 00-4D 03 03 59 82 04 A8 14 ........M..Y.... 
... 
0000:0BE0 12 0D 53 CB B6 20 64 BC-8E 77 3A 0F 0E 00 00 00 ..S.. d..w:..... 
[127.0.0.1:1962 Sent at 00:58:21.812] // ClientKeyExchange 
0000:0000 16 03 03 00 46 10 00 00-42 41 04 ED DD 67 FB 22 ....F...BA...g." 
... 
0000:0040 39 50 1F 50 F2 12 62 A7-3D C8 FE     9P.P..b.=..  
[127.0.0.1:1962 Sent at 00:58:21.828] // Client ChangeCipherSpec 
0000:0000 14 03 03 00 01 01         ......   
[127.0.0.1:1962 Sent at 00:58:21.828] // Client Finished 
0000:0000 16 03 03 00 50 8E DB DC-39 07 9B 68 36 17 BB 44 ....P...9..h6..D 
... 
0000:0050 B3 5E 91 FF E8         .^...   
[127.0.0.1:1962 Received at 00:58:21.890] // Server ChangeCipherSuite 
0000:0000 14 03 03 00 01 01         ......   
[127.0.0.1:1962 Received at 00:58:22.046] // Server Finished, but delayed 156ms !!! 
0000:0000 16 03 03 00 50 71 68 70-ED 8F D6 73 11 94 DD F4 ....Pqhp...s.... 
0000:0010 D9 A4 1F 60 BA 48 43 B0-4B 53 EF 66 E5 59 F2 8B ...`.HC.KS.f.Y.. 
0000:0020 DD CE D7 D5 8F C4 68 A2-87 07 92 A9 3B D9 9B 3B ......h.....;..; 
0000:0030 DD DE 1A 71 6F 87 8D 59-17 6F 8F 94 2C 89 01 DA ...qo..Y.o..,... 
0000:0040 E9 7D 08 E2 F2 FC 54 BF-FA 8D 45 F8 7B B0 29 8D .}....T...E.{.). 
0000:0050 CE 87 CF 81 E1         .....   
[127.0.0.1:1962 Sent at 00:58:22.046] // HTTP Request 
0000:0000 17 03 03 00 A0 73 85 EE-93 BC 66 94 76 6D 49 74 .....s....f.vmIt 
... 
0000:00A0 DE C2 BE DD 46         ....F   
[127.0.0.1:1962 Received at 00:58:22.062] // HTTP Response 
0000:0000 17 03 03 02 70 E8 CF 13-B4 E0 4F 32 8E 6F 37 74 ....p.....O2.o7t 
... 
0000:0270 DD 5B FB 99 9D         .[...   
[127.0.0.1:1962 Sent at 00:58:22.062] // Disconnect 
0000:0000 15 03 03 00 40 42 BC E5-B7 B2 E4 B5 22 D2 DF 75 [email protected]"..u 
... 
0000:0040 B8 59 B2 89 FB         .Y...   
[127.0.0.1:1962 Disconnected at 00:58:22.062] 

在测试到Tomcat服务器时,TCP转储是这样的:

... 
[127.0.0.1:1968 Received at 00:58:50.312] // server-side ChangeCipherSpec & Finished 
0000:0000 14 03 03 00 01 01 16 03-03 00 50 03 0D D0 FE 94 ..........P..... 
0000:0010 5D 0B 22 60 62 46 F3 29-D9 37 B7 D1 42 60 5A 6A ]."`bF.).7..B`Zj 
0000:0020 93 C8 1F CF D8 B9 81 7D-DD 3D A9 1E A0 F0 C0 05 .......}.=...... 
0000:0030 11 C8 C4 B9 31 16 E5 1E-2F 43 EA 45 2A F0 E8 BF ....1.../C.E*... 
0000:0040 9E BD 20 84 8E 5A 1A 57-0B 31 32 BE 5E 6C B3 F3 .. ..Z.W.12.^l.. 
0000:0050 6A 00 95 D3 75 32 03 35-83 3D 12     j...u2.5.=.  
... 

有没有用的SSLContext,KeyManagers或使用问题我的Java代码中的SSL握手?

回答

-1

读取Tomcat的源代码之后,我除去延迟简单地通过使TCP_NODELAY

   Socket socket = server.accept(); 
       socket.setTcpNoDelay(true); 
       // ((SSLSocket) socket).getSession(); 

UPDATE-1

和Tomcat使TCP_NODELAY对于每个接受的套接字。见Tomcat的郊狼源(8.0.x)org.apache.tomcat.util.net.SocketProperties行155:

/** 
* TCP_NO_DELAY option. JVM default used if not set. 
*/ 
protected Boolean tcpNoDelay = Boolean.TRUE; 

和2 setProperties方法,一旦插座accpeted被调用。

UPDATE-2

JVM禁用TCP_NODELAY默认的,这意味着Nagle算法可以延迟发送小字节。显然,服务器已完成被Nagle的算法推迟。

很多关于TCP_NODELAY的文章可以用Google搜索。

+0

如果默认情况下已启用,那么如何启用它来修复它?或者改变一切? – EJP

+0

对不起。更改为* tomcat为每个接受的套接字启用TCP_NODELAY * – auntyellow

+0

同样的问题。没有什么变化,在套接字中,或者在物质上,在你的答案中。如果它已经启用,那么如何启用它来解决问题?或改变任何事情。 – EJP

相关问题