2017-08-03 56 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

相關問題