Content-Type: application/x-www-form-urlencoded
Accept: */*
Connection: keep-alive
Cookie: Hm_lvt_f674b880b5ccff4b49dea707ae6d0a59=1458724181
User-Agent: dabaimama/1.9.1 (iPhone; iOS 9.1; Scale/2.00)
Accept-Language: zh-Hans-CN;q=1
Accept-Encoding: gzip, deflate
Content-Length: 263
Date: Wed, 30 Mar 2016 09:52:48 GMT
Server: Apache/2.2.15 (CentOS)
Content-Length: 770
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/json;charset=UTF-8
{"result":[{"msg":"","commstar":"","productId":"0","nickName":"","sex":"0","stars":"0","askerId":"2195","babyAge":"0","recordId":"119405","realName":"","ageStr":"","doctorId":"0","createT":"03-29 18:36","doctors":"","babySex":"0","babyLogo":"","evalutionmsg":"","logo":"","babyName":"","lastmsg":"{\"body\":\"匿名向您諮詢\",\"feedbackstatus\":\"0\",\"from\":\"huser2195\",\"kbubblecolor\":\"0\",\"msgId\":\"1459247810.789\",\"nickName\":\"\",\"recordid\":\"119405\",\"to\":\"huser315\",\"type\":\"notice\",\"userLogo\":\"\"}","finshT":"","age":"0","babyAgeStr":"","status":"0"}],"msg":"success","comm":{"userId":"315","phoneType":"","phoneToken":"13984b70f5705d9e44f61d004d7ad563ff31577139e0dadd90d674555b664a5d","clientVersion":"2.0.1"},"code":"200","status":"1"}
HTTP/1.1 200 OK
這個部分需要講的是錯誤碼。事實上HTTP請求錯誤碼可以根據錯誤碼從左往右第一個數字大致分爲以下幾類:
1XX:信息提示。不代表成功或者失敗,表示臨時響應,比如100表示繼續,101表示切換協議
2XX: 成功
3XX: 重定向
4XX:客戶端錯誤,很有可能是客戶端發生問題,如親切可愛的404表示未找到文件,說明你的URI是有問題的,服務器機子上該目錄是沒有該文件的;414URI太長
5XX: 服務器錯誤,比如504網關超時
錯誤碼是不用去記的,出錯了再查對應的錯誤碼含義就行。但是知道上面的分類有助於第一時間做出大體的判斷,起碼你能清楚是服務端還是客戶端的原因。
這裏我把HTTP版本簡單分爲三類:1.1之前,1.1,2.0,針對這三類做個主要差異的介紹:
HTTP 1.1之前
-
不支持持久連接。一旦服務器對客戶端發出響應就立即斷開TCP連接
-
無請求頭跟響應頭
-
客戶端的前後請求是同步的。下一個請求必須等上一個請求從服務端拿到響應後才能發出,有點類似多線程的同步機制。
HTTP 1.1(主流版本)
與1.1之前的版本相比,做了以下性能上的提升
-
增加請求頭跟響應頭
-
支持持久連接。客戶端通過請求頭中指定Connection爲keep-alive告知服務端不要在完成響應後立即釋放連接。HTTP是基於TCP的,在HTTP 1.1中一次TCP連接可以處理多次HTTP請求
-
客戶端不同請求之間是異步的。下一個請求不必等到上一個請求回來後再發出,而可以連續發出請求,有點類似多線程的異步處理。
HTTP 2.0
本着向下兼容的原則,1.1版本有的特性2.0都具備,也使用相同的API。但是2.0將只用於https網址。由於2.0的普及還需要比較長的一段時間,這裏不展開,更多新特性請參考這篇文章。
我們重點關注一下當前1.1版本所做幾點改變。支持持久連接有什麼好處呢?HTTP是基於TCP連接的,如果連接被頻繁地啓動然後斷開就會花費很多資源在TCP三次握手以及四次揮手上,效率低下。以請求一個網頁爲例,我們知道,一個html網頁上的圖片資源並不是直接嵌入在網頁上,而只是提供url,圖片仍需要額外發HTTP 請求去下載。一個網頁從請求到最終加載到本地往往需要經過過個HTTP請求。在1.1版本之前請求一個網頁就需要發生多次"握手-揮手"的過程,每次連接之間相互獨立;而1.1及之後的版本最少只需要一次就夠。
HTTP是應用層的協議,更靠近用戶端;TCP是傳輸層的協議;而socket是從傳輸層上抽象出來的一個抽象層,本質是接口。所以本質上三種還是很好區分的。儘管如此,有時候你可能會懵逼,HTTP連接、TCP連接、socket連接有什麼區別?好吧,如果上面的圖解釋的還是不夠清楚的話,我們繼續往下看。
1、TCP連接與HTTP連接的區別
上文提過,HTTP是基於TCP的,客戶端往服務端發送一個HTTP請求時第一步就是要建立與服務端的TCP連接,也就是先三次握手,“你好,你好,你好”。從HTTP 1.1開始支持持久連接,也就是一次TCP連接可以發送多次的HTTP請求。
小總結:HTTP基於TCP
2、TCP連接與Socket連接的區別
在圖4.1中我們提到,socket層只是在TCP/UDP傳輸層上做的一個抽象接口層,因此一個socket連接可以基於連接,也有可能基於UDP。基於TCP協議的socket連接同樣需要通過三次握手建立連接,是可靠的;基於UDP協議的socket連接不需要建立連接的過程,不過對方能不能收到都會發送過去,是不可靠的,大多數的即時通訊IM都是後者。
小總結:Socket也基於TCP
3、HTTP連接與Socket連接的區別
區分這兩個概念是比較有意義的,畢竟TCP看不見摸不着,HTTP與Socket是實實在在能用到的。
-
HTTP是短連接,Socket(基於TCP協議的)是長連接。儘管HTTP1.1開始支持持久連接,但仍無法保證始終連接。而Socket連接一旦建立TCP三次握手,除非一方主動斷開,否則連接狀態一直保持。
-
HTTP連接服務端無法主動發消息,Socket連接雙方請求的發送先後限制。這點就比較重要了,因爲它將決定二者分別適合應用在什麼場景下。HTTP採用“請求-響應”機制,在客戶端還沒發送消息給服務端前,服務端無法推送消息給客戶端。必須滿足客戶端發送消息在前,服務端回覆在後。Socket連接雙方類似peer2peer的關係,一方隨時可以向另一方喊話。
4、問題來了:什麼時候該用HTTP,什麼時候該用socket
這個問題的提出是很自然而然的。當你接到一個與另一方的網絡通訊需求,自然會考慮用HTTP還是用Socket。
-
用HTTP的情況:雙方不需要時刻保持連接在線,比如客戶端資源的獲取、文件上傳等。
-
用Socket的情況:大部分即時通訊應用(QQ、微信)、聊天室、蘋果APNs等
在iOS中,發HTTP請求一般用原生的NSURLConnection、NSURLSession或者開源的AFNetWorking(推薦)、ASIHttpRequest(已停止更新)。連接Socket連接我用的比較多是robbiehanson大神的CocoaAsyncSocket(XMPPFramework也是出自他手)。