我們知道,tcp建立連接配接時會進行三次握手,而握手是以一方發送一個syn為開始的。下載下傳抓包工具wireshark之後,進行抓包調試。在java裡實作了一段模拟請求的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<code>package</code> <code>test;</code>
<code> </code>
<code>import</code> <code>java.io.ioexception;</code>
<code>import</code> <code>org.apache.commons.httpclient.httpclient;</code>
<code>import</code> <code>org.apache.commons.httpclient.httpexception;</code>
<code>import</code> <code>org.apache.commons.httpclient.simplehttpconnectionmanager;</code>
<code>import</code> <code>org.apache.commons.httpclient.methods.getmethod;</code>
<code>import</code> <code>org.junit.test;</code>
<code>/**</code>
<code> </code> <code>* todo comment of testhttpclient</code>
<code> </code> <code>*</code>
<code> </code> <code>* yihua.huang</code>
<code> </code> <code>*/</code>
<code>public</code> <code>class</code> <code>testhttpclient {</code>
<code> </code> <code></code>
<code> </code> <code>public</code> <code>void</code> <code>testheader() {</code>
<code> </code> <code>httpclient httpclient = </code><code>new</code> <code>httpclient(</code> <code>new</code> <code>simplehttpconnectionmanager(</code> <code>true</code> <code>));</code>
<code> </code> <code>httpclient.gethttpconnectionmanager().getparams().setsotimeout(</code> <code>5000</code> <code>);</code>
<code> </code> <code>httpclient.gethttpconnectionmanager().getparams().setconnectiontimeout(</code> <code>5000</code> <code>);</code>
<code> </code> <code>getmethod get = </code><code>new</code> <code>getmethod(</code> <code>""</code> <code>);</code>
<code> </code> <code>try</code> <code>{</code>
<code> </code> <code>httpclient.executemethod(get);</code>
<code> </code> <code>} </code><code>catch</code> <code>(httpexception e) {</code>
<code> </code> <code>// todo auto-generated catch block</code>
<code> </code> <code>e.printstacktrace();</code>
<code> </code> <code>} </code><code>catch</code> <code>(ioexception e) {</code>
<code> </code> <code>}</code>
<code> </code> <code>thread.sleep(</code> <code>10000</code> <code>);</code>
<code> </code> <code>} </code><code>catch</code> <code>(interruptedexception e1) {</code>
<code> </code> <code>e1.printstacktrace();</code>
<code> </code> <code>get = </code><code>new</code> <code>getmethod(</code> <code>""</code> <code>);</code>
<code> </code> <code>get.setrequestheader(</code> <code>"connection"</code> <code>, </code><code>"keep-alive"</code> <code>);</code>
<code> </code> <code>}</code>
<code>}</code>
請求結果如下。可以看到,圖一中共有兩次http請求,但是隻建立了一次tcp連接配接,說明持久連接配接是有效的。而等到10秒之後(代碼40行開始)的http請求,又會重建立立連接配接,證明keep-alive已經過了逾時時間。然後在頭中加入keep-alive:
300,結果第二次請求仍然會重新連接配接,證明伺服器端對于keep-alive逾時進行了配置,并不接受keep-alive: 300頭。
圖1 第一次請求,keep-alive生效
圖2 10秒後第二次請求,keep-alive過期
然後我們将connection頭設定為close,重試。發現确實建立了兩次tcp連接配接。
圖3 設定connection:close後,keep-alive無效
總結:
keep-alive隻是http1.0時代對持久化連接配接的叫法,目前http1.1已經預設所有請求都是持久化的,rfc規範是正确的。
頭部不設定connection: keep-alive,依然會進行持久化連接配接。
如果設定connection:close,則不進行持久化連接配接。
目前連接配接過期時間在服務端設定,keep-alive頭設定逾時時間的做法已經不再有效。