上一篇描述了如何在Windows環境中快速送出封包,接下來是Linux環境了。
下列步驟適用Linux base系統:
Linux的預設安裝似乎也是沒有telnet程式,所以也必須先安裝,因為每個Linux base的安裝方式都不相同,所以可到網路查詢一下怎麼安裝telnet。下圖是CentOS的系統安裝範例:
-
輸入指令 yum install telnet (注意,yum必須在root帳號下執行)
-
安裝後的執行與Windows相同。執行telnet 192.168.21.35 8080後,貼上封包,就可以取得HTTP的Reponse了。
解析HTTP Response(回應)封包資料
在上一章我們針對HTTP的Request封包解釋過,接下來讓我們來看看HTTP的Response吧。
HTTP封包範例1
-
HTTP/1.1 302 Found
-
Server: Apache-Coyote/1.1
-
Location: http://192.168.21.35:8080/xxxx/
-
Transfer-Encoding: chunked
-
Date: Wed, 18 May 2016 03:21:21 GMT
-
0
在上一章有提過,基本上要解讀HTTP的封包,要先將封包切成三個部份:
-
第一行的宣告。
-
中間的header,以本例來說就是2~5行。
-
最後的資料。
這個部份在解讀Response的資料仍是相同的。
第一行的宣告 HTTP/1.1 302 Found ,要切開成二段來閱讀,一個是HTTP/1.1 是固定的,意思是這個封包導守HTTP 1.1的協定;第二個是302 Found,這個被稱為狀態碼,會依據伺服器的情況來回傳,而文字主要是給人閱讀的,程式主要判斷的部份是數字,每一個數字都有不同的意義,下方列出幾個最常遇到的狀態碼:
-
200 OK - 代表伺服器正常處理傳入的Request。
-
302 Found - 伺服器希望使用者連線到另一個網址,網址會帶在header裡的Location值裡面(參考封包的第三行)。
-
401 Unauthorized - 使用者未經認證,通常透過登入可以解決這個問題。
-
403 Forbidden - 使用者的權限不足,無法瀏灠指定的網頁。
-
404 Not Found - 使用者指定的網址,並無對應的網頁或資源。
-
500 Internal Server Error - 伺服器在執行對應的網址時出錯。
從第2行到第5行,就是我們熟悉的header,我們來大概瞭解一下它們的意思。
第二行的Server: Apache-Coyote/1.1,宣告的是處理這個HTTP的伺服器種類,將它的值Apache-Coyote/1.1貼到網路上做查詢,可以發現這個伺服器是用tomcat架設起來的。
第三行的Location: http://192.168.21.35:8080/xxxx/,通常這個Location header是配合302 Found的狀態碼才會有,目的是告知灠瀏器要轉連到那一個網址。
第四行的Transfer-Encoding: chunked,這個封包是以分段的方式來傳送的。通常HTTP封包會包含一個"Content-Length"的header,來告知這個封包有多大。因為HTTP是屬於TCP應用中的其中一種,所以會等候接收端的回應,如果接收端沒有回應的話,會再重新傳送一次,以防資料遺失。試想,一個封包如果帶了1MB的資料,結果全部傳送完後,接收端沒有回應,最後這個1MB的資料還要重新傳送,這是一件很搞笑的事,所以通常都會使用chunked(分段)的方式,告知每一段封包的長度,而在整份文件的最後會傳送一個0(第七行),表示整個Response傳送完畢。
第五行的Date: Wed, 18 May 2016 03:21:21 GMT,代表現在伺服器的時間。
第六行的空格是一個分隔,代表從下方開始,是Response的主體。
第七行開始開Response的主體;因為這個封包主要是要求使用者到另一個網址,所以沒有什麼內容,只回傳一個0,代表封包的結束。
HTTP封包範例2
-
HTTP/1.1 200 OK
-
Server: Apache-Coyote/1.1
-
Content-Type: text/html;charset=UTF-8
-
Content-Language: zh-TW
-
Transfer-Encoding: chunked
-
Date: Wed, 18 May 2016 06:43:18 GMT
-
2000
-
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">.......
封包的解讀方式都一樣,所以我們直接來解讀,這一封包有幾個重點:
-
狀態碼是200,代表成功取得資料。
-
第3行宣告資料的內容樣式(MINE TYPE),是text/html,而且需用UTF-8來解讀。
-
第8行的2000,代表這個封包的資料為2000位元組。
-
第9行則是實際的資料內容。
結論
其實這篇應用與上一篇是連貫的,擷取傳送到伺服器的封包後,再重覆利用傳送該封包來進行Debug,在某些狀況下非常有用的,不但可以免除一直麻煩別人進行測試,而且可以透過多次的Debug,來確保程式的正確性;甚至透過直接修改封包,來達到快速檢測的功能;以筆者曾經遇到的問題為例:
手機端的一支小程式,在下載的行為上,只能重頭下載到尾,不能支援續傳功能。
擷取封包後發現封包帶了二個相同的header,當下覺得很奇怪,就馬上
-
將封包文字複製到筆記本。
-
修改成正常的封包後。
-
透過telnet再重送一次,
結果發現回傳的內容就變正常了;從發現奇怪的狀況,到證明bug的原因,不會超過一分鐘。
以這種狀況為例,如果我們是從程式端去追查問題,可能花了不止四、五倍的時間還不一定能追查的到原因,而當我們從封包追回問題時,卻一下子就可以找出問題,所以建議讀者,當從一個面向追不到問題時,有時換個想法、作法,可能會有意向不到的效果。