目錄
四、TCP(Transmission Control Protocol,傳輸控制協議)
五、HTTP(HyperText Transfer Protocol,超文本傳輸協議)
四、TCP(Transmission Control Protocol,傳輸控制協議)
TCP是一種面向連接(連接導向)的、可靠的基於字節流的傳輸層通信協議。TCP將用戶數據打包成報文段,它發送后啟動一個定時器,另一端收到的數據進行確認、對失序的數據重新排序、丟棄重復數據。
TCP的特點有:
- TCP是面向連接的運輸層協議
- 每一條TCP連接只能有兩個端點,每一條TCP連接只能是點對點的
- TCP提供可靠交付的服務
- TCP提供全雙工通信。數據在兩個方向上獨立的進行傳輸。因此,連接的每一端必須保持每個方向上的傳輸數據序號。
- 面向字節流。面向字節流的含義:雖然應用程序和TCP交互是一次一個數據塊,但TCP把應用程序交下來的數據僅僅是一連串的無結構的字節流。
TCP/IP協議族包括運輸層、網絡層、鏈路層,而socket所在位置如圖,Socket是應用層與TCP/IP協議族通信的中間軟件抽象層。

UDP(User Data Protocol,用戶數據報協議)是與TCP相對應的協議。它是屬於TCP/IP協議族中的一種。如圖:

1、TCP頭格式

(1) Source Port(源端口號):數據發起者的端口號,16bit。
(2) Destination Port(目的端口號):數據接收者的端口號,16bit。
(3) Sequence Number(順序號碼,Seq):用於在數據通信中解決網絡包亂序(reordering)問題,以保證應用層接收到的數據不會因為網絡上的傳輸問題而亂序(TCP會用這個順序號碼來拼接數據),32bit。
(4) Acknowledgment Number(確認號碼,ack):是數據接收方期望收到發送方在下一個報文段的順序號碼(Seq),因此確認號碼應當是上次已成功收到順序號碼(Seq)加1,32bit。
(5) Offset(TCP報文頭長度):用於存儲報文頭中有多少個32bit(上圖的一行),存儲長度為4bit,最大可表示(2^3+2^2+2^1+1)*32bit=60bytes的報文頭。最小取值5,5*32bit=20bytes。
(6) Reserved(保留):6bit, 均為0
(7) TCP Flags(TCP標志位)每個長度均為1bit
CWR:壓縮,TCP Flags值0x80。
ECE:擁塞,0x40。
URG:緊急,0x20。當URG=1時,表示報文段中有緊急數據,應盡快傳送。
ACK:確認,0x10。當ACK = 1時,代表這是一個確認的TCP包,取值0則不是確認包。
PSH:推送,0x08。當發送端PSH=1時,接收端盡快的交付給應用進程。
RST:復位,0x04。當RST=1時,表明TCP連接中出現嚴重差錯,必須釋放連接,再重新建立連接。
SYN:同步,0x02。在建立連接是用來同步序號。SYN=1, ACK=0表示一個連接請求報文段。SYN=1,ACK=1表示同意建立連接。
FIN:終止,0x01。當FIN=1時,表明此報文段的發送端的數據已經發送完畢,並要求釋放傳輸連接。
(8) 窗口:用來控制對方發送的數據量,通知發放已確定的發送窗口上限。
(9) 檢驗和:該字段檢驗的范圍包括頭部和數據這兩部分。由發端計算和存儲,並由收端進行驗證。
(10) 緊急指針:緊急指針在URG=1時才有效,它指出本報文段中的緊急數據的字節數。
(11) TCP選項:長度可變,最長可達40字節
備注:ISN(Inital Sequence Number):初始化Sequence Number,發生在建立連接時。
2、TCP協議中的三次握手和四次揮手

特別注意
Seq:是發送方當前報文的順序號碼。
ack:是發送方期望對方在下次返回報文中給回的Seq。
建立連接需要三次握手
第一次握手:客戶端向服務端發送連接請求包,標志位SYN(同步序號)置為1,順序號碼為X=0。
第二次握手:服務端收到客戶端發過來報文,由SYN=1知道客戶端要求建立聯機,則為這次連接分配資源。並向客戶端發送一個SYN和ACK都置為1的TCP報文,設置初始順序號碼Y=0,將確認序號(ack)設置為上一次客戶端發送過來的順序號(Seq)加1,即X+1 = 0+1=1。
第三次握手:客戶端收到服務端發來的包后檢查確認號碼(ack)是否正確,即第一次發送的Seq加1(X+1=1)。以及標志位ACK是否為1。若正確,服務端再次發送確認包,ACK標志位為1,SYN標志位為0。確認號碼(ack)=Y+1=0+1=1,發送順序號碼(Seq)為X+1=1。Server收到后確認號碼值與ACK=1則連接建立成功,可以傳送數據了。
斷開連接需要四次揮手
提醒:中斷連接端可以是Client端,也可以是Server端。只要將下面兩角色互換即可。
第一次揮手:客戶端給服務端發送FIN報文,用來關閉客戶端到服務端的數據傳送。將標志位FIN和ACK置為1,順序號碼為X=1,確認號碼為Z=1。意思是說”我Client端沒有數據要發給你了,但是如果你還有數據沒有發送完成,則不必急着關閉Socket,可以繼續發送數據。所以你先發送ACK過來。”
第二次揮手:服務端收到FIN后,發回一個ACK(標志位ACK=1),確認號碼為收到的順序號碼加1,即X=X+1=2。順序號碼為收到的確認號碼=Z。意思是說“你的FIN請求我收到了,但是我還沒准備好,請繼續你等我的消息" 這個時候客戶端就進入FIN_WAIT狀態,繼續等待服務端的FIN報文。
第三次揮手:當服務端確定數據已發送完成,則向客戶端發送FIN報文,關閉與客戶端的連接。標志位FIN和ACK置為1,順序號碼為Y=1,確認號碼為X=2。意思是告訴Client端“好了,我這邊數據發完了,准備好關閉連接了。”
第四次揮手:客戶端收到服務器發送的FIN之后,發回ACK確認(標志位ACK=1),確認號碼為收到的順序號碼加1,即Y+1=2。順序號碼為收到的確認號碼X=2。意思是“我Client端知道可以關閉連接了,但是我還是不相信網絡,怕 Server端不知道要關閉,所以發送ACK后進入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳。Client端等待了2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,我Client端也可以關閉連接了。“(在TIME_WAIT狀態中,如果TCP client端最后一次發送的ACK丟失了,它將重新發送。TIME_WAIT狀態中所需要的時間是依賴於實現方法的。典型的值為30秒、1分鍾和2分鍾。等待之后連接正式關閉,並且所有的資源(包括端口號)都被釋放。)
為什么關閉的時候卻是四次揮(握)手?
因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。
3、TCP報文抓取工具:Wireshark
捕獲過濾器中填入表達式:host www.cnblogs.com and port 80(80等效於http)
有多個TCP流時在顯示過濾器中填入表達式:tcp.stream eq 0 篩選出第一個TCP流(包含完整的一次TCP連接:三次握手和四次揮手)


每條記錄都有如下協議層
(1) Frame: 物理層的數據幀概況
(2)Ethernet II: 數據鏈路層以太網幀頭部信息
(3) Internet Protocol Version 4: 互聯網層IP包頭部信息
(4)Transmission Control Protocol: 傳輸層的數據段頭部信息,此處是TCP
(5) Hypertext Transfer Protocol: 應用層的信息,此處是HTTP協議

五、HTTP(HyperText Transfer Protocol,超文本傳輸協議)
HTTP是一個應用層協議,雖然在2015年已推出HTTP/2版本,並被主要的web瀏覽器和web服務器支持。但目前使用最廣泛的還是HTTP/1.1版本。有關歷史請查閱這里。
它的主要特點可概括如下:
- 支持客戶/服務器模式。
- 簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。由於HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度很快。
- 靈活:HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
- 無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。
- 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味着如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。為了解決這個問題, Web程序引入了Cookie機制來維護狀態。
另外,HTTP請求報文和響應報文都是由開始行(對於請求消息,開始行就是請求行,對於響應消息,開始行就是狀態行),消息報頭(可選),空行(只有CRLF的行),消息正文(可選)組成。將在下面詳細講解。
1、請求報文結構
報文中的數據都使用ASCII編碼,各個字段的長度是不確定的(除了作為結尾的CRLF外,不允許出現單獨的CR或LF字符)。

2、請求報文樣例
POST /search HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-silverlight, application/x-shockwave-flash, */* Referer: http://www.google.cn/ Accept-Language: zh-cn Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld) Host: www.google.cn Connection: Keep-Alive Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g; NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y- FxlRugatx63JLv7CWMD6UB_O_r hl=zh-CN&source=hp&q=domety
3、請求報文參數詳解
請求方法
所有請求方法名稱全為大寫,目前有9種:
備注
安全性:https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
冪等性:表示的操作至多只會被處理一次,每次調用都將返回第一次調用時的處理結果。
關於HTTP請求GET和POST的區別
(1).提交形式:
GET提交的數據會放在URL之后,以?分割URL和傳輸數據,參數之間以&相連,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的Body中.
(2).傳輸數據的大小:
HTTP協議本身沒有對傳輸的數據大小進行限制,HTTP協議規范也沒有對URL長度進行限制。 而在實際開發中存在的限制主要有:
GET:特定瀏覽器和服務器對URL長度有限制,例如IE對URL長度的限制是2083字節(2K+35)。對於其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決於操作系統的支持。
因此對於GET提交時,傳輸數據就會受到URL長度的限制。
POST:由於不是通過URL傳值,理論上數據不受限。但實際各個WEB服務器會規定對post提交數據大小進行限制,Apache、IIS6都有各自的配置。
(3).安全性:
POST的安全性要比GET的安全性高,具有真正的Security的含義。而且通過GET提交數據,用戶名和密碼將明文出現在URL上,因為登錄頁面有可能被瀏覽器緩存,其他用戶瀏覽歷史紀錄就可以拿到賬號和密碼了。
請求報頭域
報頭域指頭部中的Key,且不分大小寫。

4、響應報文結構
如所見,響應報文結構與請求報文結構唯一真正的區別在於第一行中用狀態信息代替了請求信息。狀態行(status line)通過提供一個狀態碼來說明所請求的資源情況。

5、響應報文樣例
HTTP/1.1 200 OK Date: Mon, 23 May 2005 22:38:34 GMT Content-Type: text/html; charset=UTF-8 Content-Encoding: UTF-8 Content-Length: 138 Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux) ETag: "3f80f-1b6-3e1cb03b" Accept-Ranges: bytes Connection: close <html> <head> <title>An Example Page</title> </head> <body> Hello World, this is a very simple HTML document. </body> </html>
6、響應報文參數詳解
響應狀態碼
狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。
1xx:指示信息--表示請求已接收,繼續處理。
2xx:成功--表示請求已被成功接收、理解、接受。
3xx:重定向--要完成請求必須進行更進一步的操作。
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現。
5xx:服務器端錯誤--服務器未能實現合法的請求。
常用狀態碼:
200 OK:成功返回狀態,對應,GET,PUT,PATCH,DELETE。
201 created - 成功創建。
302 Found:重定向,新的URL會在response中的Location中返回,瀏覽器將會使用新的URL發出新的Request。
例如在IE中輸入http://www.google.com. HTTP服務器會返回304, IE取到Response中Location header的新URL, 又重新發送了一 個 Request.
304 Not Modified:代表上次的文檔已經被緩存了, 還可以繼續使用。
400 bad request - 請求格式錯誤。
401 unauthorized - 未授權。
403 forbidden - 鑒權成功,但是該用戶沒有權限。
404 not found - 請求的資源不存在。
405 method not allowed - 該http方法不被允許。
410 gone - 這個url對應的資源現在不可用。
415 unsupported media type - 請求類型錯誤。
422 unprocessable entity - 校驗錯誤時用。
429 too many request - 請求過多。
500 Internal Server Error:服務器發生了不可預期的錯誤。
503 Server Unavailable:服務器當前不能處理客戶端的請求,一段時間后可能恢復正常。
響應報頭域
報頭域指頭部中的Key,且不分大小寫。

7、HTTP報文抓取工具
Wireshark、Fiddler、HttpWatch(需結合IE)、Telnet
Wireshark:
在顯示過濾器中填入表達式:http and ip.addr == 42.121.252.58 and tcp.port == 80 過濾出http的響應和請求流程

8、Session和Cookie
說到HTTP,就不得不提Session和Cookie。但嚴格來說,Session和Cookie並不是http協議的一部分。由於HTTP協議設計原則是無狀態的,但是近年來出現了種種需求,其中cookie的作用就是為了解決HTTP協議無狀態的缺陷所作出的努力。后來出現的session機制則是又一種在客戶端與服務器之間保持狀態的解決方案。 具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由於采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助於cookie機制來達到保存標識的目的,但實際上它還有其他選擇。
Session
Session是可以存儲針對於某一個用戶的瀏覽器以及通過其當前窗口打開的任何窗口具有針對性的用戶信息存儲機制。
通常大家認為,只要關閉瀏覽器,session就消失,其實這是錯誤的理解。對session來說也是一樣的,除非程序通知服務器刪除一個session,否則服務器會一直保留。由於關閉瀏覽器不會導致session被刪除,迫使服務器為seesion設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把session刪除以節省存儲空間.
(1)第一次訪問某個web站點資源時,客戶端提交沒有帶SessionID的請求(請求報文頭沒有Cookie頭域信息)。
而web服務器會檢查是否有SessionID過來,沒有則創建SessionID,並根據web程序自身定義在請求哪個資源時添加屬於當前會話的信息(也可為空),這個信息列表以SessionID作為標識。然后將SessionID返回給客戶端(通過響應報文頭的Set-Cookie頭域)。
(2 )客戶端再次訪問同個web站點時,提交帶有SessionID的請求(通過Cookie頭域存儲SessionID)。由服務端判斷session是否失效,如果未失效,可查詢屬於當前會話的信息列表。如果失效,則創建新的session(產生新的SessionID),而原先的session(包含session帶的信息列表)則丟失,無法訪問。


Cookie
保存SessionID的方式可以采用Cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個SessionID發回給服務器。Cookie的命名方式類似於SessionID。有時Cookie被人為的禁止,所以出現了其他機制以便在Cookie被禁止時仍然能夠把SessionID傳遞回服務器。這種技術叫做URL重寫,就是把SessionID直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為http://www.wantsoft.com/index.asp;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 。
另一種是作為查詢字符串附加在URL后面,表現形式為http://www.wantsoft.com/index?js ... 99zWpBng!-145788764 。
六、TCP和UDP的區別
TCP與UDP基本區別 :
- 基於連接與無連接
- TCP要求系統資源較多,UDP較少
- UDP程序結構較簡單
- 流模式(TCP)與數據報模式(UDP)
- TCP保證數據正確性,UDP可能丟包
- TCP保證數據順序,UDP不保證
UDP應用場景:
- 面向數據報方式
- 網絡數據大多為短消息
- 擁有大量Client
- 對數據安全性無特殊要求
- 網絡負擔非常重,但對響應速度要求高
具體編程時的區別:
- socket()的參數不同
- UDP Server不需要調用listen和accept
- UDP收發數據用sendto/recvfrom函數
- TCP:地址信息在connect/accept時確定
- UDP:在sendto/recvfrom函數中每次均 需指定地址信息
- UDP:shutdown函數無效
編程區別
通常我們在說到網絡編程時默認是指TCP編程,即用前面提到的socket函數創建一個socket用於TCP通訊,函數參數我們通常填為SOCK_STREAM。即socket(PF_INET, SOCK_STREAM, 0),這表示建立一個socket用於流式網絡通訊。
SOCK_STREAM這種的特點是面向連接的,即每次收發數據之前必須通過connect建立連接,也是雙向的,即任何一方都可以收發數據,協議本身提供了一些保障機制保證它是可靠的、有序的,即每個包按照發送的順序到達接收方。
而SOCK_DGRAM這種是User Datagram Protocol協議的網絡通訊,它是無連接的,不可靠的,因為通訊雙方發送數據后不知道對方是否已經收到數據,是否正常收到數據。任何一方建立一個socket以后就可以用sendto發送數據,也可以用recvfrom接收數據。根本不關心對方是否存在,是否發送了數據。它的特點是通訊速度比較快。大家都知道TCP是要經過三次握手的,而UDP沒有。
基於上述不同,UDP和TCP編程步驟也有些不同,如下:
TCP:
TCP編程的服務器端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt(); * 可選
3、綁定IP地址、端口等信息到socket上,用函數bind();
4、開啟監聽,用函數listen();
5、接收客戶端上來的連接,用函數accept();
6、收發數據,用函數send()和recv(),或者read()和write();
7、關閉網絡連接;
8、關閉監聽;
TCP編程的客戶端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、端口等信息到socket上,用函數bind();* 可選
4、設置要連接的對方的IP地址和端口等屬性;
5、連接服務器,用函數connect();
6、收發數據,用函數send()和recv(),或者read()和write();
7、關閉網絡連接;
UDP:
與之對應的UDP編程步驟要簡單許多,分別如下:
UDP編程的服務器端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、端口等信息到socket上,用函數bind();
4、循環接收數據,用函數recvfrom();
5、關閉網絡連接;
UDP編程的客戶端一般步驟是:
1、創建一個socket,用函數socket();
2、設置socket屬性,用函數setsockopt();* 可選
3、綁定IP地址、端口等信息到socket上,用函數bind();* 可選
4、設置對方的IP地址和端口等屬性;
5、發送數據,用函數sendto();
6、關閉網絡連接;
TCP和UDP是OSI模型中的運輸層中的協議。TCP提供可靠的通信傳輸,而UDP則常被用於讓廣播和細節控制交給應用的通信傳輸。
UDP補充:
UDP不提供復雜的控制機制,利用IP提供面向無連接的通信服務。並且它是將應用程序發來的數據在收到的那一刻,立刻按照原樣發送到網絡上的一種機制。即使是出現網絡擁堵的情況下,UDP也無法進行流量控制等避免網絡擁塞的行為。此外,傳輸途中如果出現了丟包,UDO也不負責重發。甚至當出現包的到達順序亂掉時也沒有糾正的功能。如果需要這些細節控制,那么不得不交給由采用UDO的應用程序去處理。換句話說,UDP將部分控制轉移到應用程序去處理,自己卻只提供作為傳輸層協議的最基本功能。UDP有點類似於用戶說什么聽什么的機制,但是需要用戶充分考慮好上層協議類型並制作相應的應用程序。
TCP補充:
TCP充分實現了數據傳輸時各種控制功能,可以進行丟包的重發控制,還可以對次序亂掉的分包進行順序控制。而這些在UDP中都沒有。此外,TCP作為一種面向有連接的協議,只有在確認通信對端存在時才會發送數據,從而可以控制通信流量的浪費。TCP通過檢驗和、序列號、確認應答、重發控制、連接管理以及窗口控制等機制實現可靠性傳輸。
TCP與UDP區別總結:
1、TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接
2、TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重復,且按序到達;UDP盡最大努力交付,即不保 證可靠交付
3、TCP面向字節流,實際上是TCP把數據看成一連串無結構的字節流;UDP是面向報文的
UDP沒有擁塞控制,因此網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如IP電話,實時視頻會議等)
4、每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
5、TCP首部開銷20字節;UDP的首部開銷小,只有8個字節
6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道
七、相關資料
- 《系統架構設計師教程》
- 《C#網絡應用編程》(第2版)
- Hypertext Transfer Protocol -- HTTP/1.1
- OSI model
- TCP/IP Reference
- wireshark抓包圖解 TCP三次握手/四次揮手詳解
- TCP 的那些事兒(上)
- TCP協議中的三次握手和四次揮手(圖解)
- Hypertext Transfer Protocol
- HTTP 協議詳解
- HTTP請求報文和HTTP響應報文
- HTTP協議詳解(經典)
- HTTP協議之Session和Cookie
