? ? ? ? 在網絡原理中主要學習TCP/IP四層模型中的重點網絡協議
1. 應用層
1.1 應用程序與協議
? ? ? ? 應用層是和程序員接觸最密切的;
????????應用程序:在應用層這里,很多時候都是程序員自定義應用層協議(步驟:1、根據需求,明確要傳輸的信息,2、約定好信息按照什么樣的格式來組織)的;所謂的網絡協議其實就是約定,即程序員在代碼中規(guī)劃好,數據如何進行傳輸;
????????下面是自定義協議的例子:
1、點外賣
????????點開外賣軟件,首先會看到商家列表,?這里就涉及到程序和服務器之間進行的網絡通信交互2、請求: 用戶信息, 位置信息,
????????此處假設就使用簡單的格式來組織,使用文本的方式.三個屬性,使用""來分割
1000,100,30()--->代碼中構造出一個這樣的字符串,給寫入到 Tcp socket 或者 Udp 的 socket 中3、響應: 商家列表(多個商家),每個商家,包含 名稱,圖片,距離,簡介,評分.
????????此處假設使用簡單的格式來組織,使用文本的方式,每個商家信息占一行,每個屬性使用","來分割
過橋米線,圖片地址1,1.1km,評分5
張亮麻辣燙,圖片地址2,2.3km,評分4.8
魏家涼皮,圖片地址3,3km,評分4.9????????上述這個過程,就是自定義協議.針對這里的情況,使用啥樣的格式來組織,只要客戶端和服務器雙方能夠對應上都是可以的;
1.2?開發(fā)中構造協議的格式
1.2.1 xml
????????(通過標簽來組織數據)
? ? ? ? 早期的組織數據的格式,現在幾乎很少用于網絡通信,下圖是代碼展示:
xml 的優(yōu)勢:
????????讓數據的可讀性變的更好;xml 的劣勢:
????????標簽寫起來非常繁瑣,傳輸的時候也占用更多網絡帶寬,(maven, 就會使用 xml 來管理項目配置)
1.2.2 json
????????(當下最流行的一種數據組織格式)
???????? json格式使用鍵值對,通過{ }把所有的鍵值對給包裹起來,鍵值對之間,使用","來分割,鍵和值之間,使用 ": ” 來分割,其中鍵固定就是 string 類型,值的話,可以是數字,可以是字符串,也可以是 json,還可以是數組;由于 json 的 key 固定就是字符串類型,很多時候也是可以把 key 的引號給省略的
? ? ? ? 下圖是代碼展示:
json 的優(yōu)勢:
????????可讀性比較好的; 比 xml 更簡潔.
json 的劣勢:????????
????????同樣也是會在網絡傳輸中,消耗額外的帶寬 (需要把 key 也進行傳輸的)雖然如此,json 在網絡通信中仍然非常流行,除非是些對于性能要求非常高的場景,不使用json 之外,其余的很多地方都可以使用 json
1.2.3 protobuffer
????????相比于json 和 xml 來說,protobufer (簡稱為 pb)使用二進制的方式來組織數據,可以保證帶寬占用最低(相當于把要傳遞的信息按照二進制形式壓縮了)
pb 的優(yōu)勢:.
????????占用帶寬最低,傳輸效率最高.非常適合于對于性能要求比較高的場景,
pb的劣勢
????????可讀性不好(二進制結構,肉眼無法直接閱讀),一定程度的影響開發(fā)效率,
????????應用層中也有一些"現成"的應用層協議,其中最知名的,最廣泛使用的,就是 HTTP 協議了(超文本傳輸協議)~~>“超文本”不僅僅是文本,還有圖片,視頻,音頻,字體..?
2.?傳輸層
? ? ? ? 傳輸層中使用到的協議主要有TCP和UDP協議:
????????端口號:寫一個服務器,必須手動指定一個端口號,通過端口來區(qū)分當前這個主機上的不同的應用程用,客戶端在通信的時候也會有一個端口號(代碼中感受不到),系統(tǒng)自動分配的一個客戶端,
????????端口號,固定就是占2 個字節(jié).表示的數據范圍0->65535,一般來說,0是不用的.其中1-1023 稱為"知名端口號,1024-65535 普通的端口號,平時自己寫代碼,用的端口還是普通的端口號為好一點;
2.1?UDP協議
2.1.1 udp報文格式
????????學習一個協議,其中最主要的工作,就是去理解協議報文格式。
? ? ? ? udp協議的報文格式總體如下圖所示:
? ? ? ? udp協議的報文格式的詳細分析圖如下圖所示:
? ? ? ?源 ip, 目的 ip 不在傳輸層,而是在網絡層 (IP 協議里);像UDP,TCP這樣的報文格式,是最初一些大佬們設計并約定出來的內容,最后被整理成了一份標準文檔,稱為RFC標準文檔;
2.1.2 報文案例分析
? ? ? ? 用戶使用瀏覽器進行搜索原理如下圖所示:
????????于業(yè)務的發(fā)展,搜集信息越來越多了,樣式也越來越復雜了.導致商搜服務器和入口服務器之間交互的數據量,已經接近 64kb (udp報文長度就是64kb)了.如果超過上限,數據就會出現截斷,最終展示在頁面上的數據肯定就會出錯
????????方案一:把數據拆分成多個包,使用多個 UDP 數據報進行傳輸.(開發(fā)成本,比較大)? ? ? ?
????????方案二:直接使用 TCP.TCP 沒有數據包的大小限制.
2.1.3 關于校驗和
? ? ? ? ?校驗和是計算機中非常廣泛使用的概念.由于在網絡傳輸中,一些設備被外部干擾,就可能會出現數據傳輸出錯的情況.在數據傳輸的過程中低電平被干擾之后擾下就成了高電平,因此, 就需要校驗和這一方法來識別出出錯的數據.
????????校驗和,其實本質上也是一個字符串,體積比原始的數據更小,又是通過原始的數據生成的.
如果接收方收到的原始數據相同,得到的校驗和就一定相同,;同理,校驗和相同,原始數據大概率相同 (理論上會存在不同的情況, 實際的概率非常低,可以忽略不計)
????????如何基于校驗和來完成數據校驗呢
1、發(fā)送方,把要發(fā)送的數據整理好(稱為 data1),通過一定的算法,計算出校驗和 checksum1;2、發(fā)送方把data1和checksun1一同發(fā)送出去;
3、接收方收到數據,收到的數據稱為 data2(數據可能和 data1 就不一樣了),收到數據 checksum1;
4、接收方再根據 data2 重新計算校驗和 (按照相同的算法),得到 checksum2
5、對比 checksum1 和 checksum2 是否相同.如果不同,則認為 data2 和 data1 一定不相同
如果 checksum1 和 checksum2 相同,則認為 data1 和 data2 大概率是相同的(理論上存在不同的可能性,概率比較低,工程上忽略不計)
? ? ? ? 關于校驗和的計算方法:
????????計算校驗和,有很多種算法,
1、此處 UDP 中使用的是 CRC 算法(循環(huán)冗余算法)
????????把當前要計算校驗和的數據,每個字節(jié),都進行累加,把結果保存到這?兩個字節(jié)的變量中,累加過程中如果溢出,也沒關系;如果中間某個數據,出現傳輸錯誤,第二次計算的校驗和就會和第一次不同
????????CRC 這個算法其實不是特別的靠譜,導致兩個不同的數據,得到相同的 crc 校驗和的概率比較大(前一個字節(jié)恰好少1,后一一個字節(jié)恰好多1.)2、md5/sha1 算法 (就只介紹 md5)
????????這里有一系列的公式,來完成 md5 的計算,(咱們不需要考慮公式是啥樣的,是一個
數學問題),但是咱們需要知道 md5 的特點:????????1.定長,無論你原始數據多長,計算得到的 md5,都是固定長度->校驗和本身就不應該很長,要不然不方便網絡傳輸
????????2.分散,給定兩個原始數據,哪怕絕大部分內容都一樣,只要其中一個字節(jié)不同,得到的 md5 值都會差異很大(md5 也非常適合作為 hash 算法)
????????3.不可逆。給定一個原始數據, 計算 md5,非常容易。但是給定?一個md5,還原出原始數據, 計算量非常龐入,以至于超出了現有計算機的算力極限,理論上是不可行的.
2.1.4 關于udp的特點分析
? ? ? ? 通過之前所寫的基于udp實現的通信代碼來分析相關的特點:
1、無連接.UDP 協議本身不會存儲對端的信息,要在發(fā)送數據的時候,顯式指定要傳輸給誰
2、不可靠,代碼中體現不出來
3、面向數據報
4、全雙工 通過一個 socket,既可以 send, 又可以 receive
?2.1.5?基于UDP的應用層協議
NFS:網絡文件系統(tǒng)
TFTP:簡單文件傳輸協議
DHCP:動態(tài)主機配置協議
BOOTP:啟動協議(用于無盤設備啟動)
DNS:域名解析協議
2.2?TCP協議
????????TCP協議最大的特點就是可靠性傳輸;
2.2.1 TCP報文格式
????????TCP報文格式如下圖所示:
? ? ? ? 首先:數據報 = 首部(報頭 header) + 載荷?
四位首部長度:
????????tcp報頭長度是不固定的,報頭最短,是20字節(jié)(沒有選項);報頭最長是60字節(jié)(一般來說選項最長的是40字節(jié)),4bit=>(0,0XF)此處的單位是4字節(jié)
保留(6位):
????????UDP 有個問題,udp報文長度 64kb是固定的;所謂的保留位, 就是當前現在不用,但是先占個位置,后面如果有需要,再使用.(留下了擴展的余地~~)
16位檢驗和:
????????和 udp 一樣的校驗和一樣;
2.2.2 關于可靠傳輸
????????可靠傳輸,是 TCP 最最核心的特性 (初心),并不是說,發(fā)送方把數據能夠 100% 的傳輸給接收方,而是退而求其次:
1、發(fā)送方發(fā)出去數據之后,能夠知道接收方是否收到數據.
2、一旦發(fā)現對方沒收到,就可以通過一系列的手段來"補救.
????????下面是一些確保信息可靠傳輸的補救手段:
1、確認應答
????????發(fā)送方,把數據發(fā)給接收方之后,接收方收到數據就會給發(fā)送方返回一個應答報文(acknowledge, ack).發(fā)送方如果收到這個應答報文了,就知道自己的數據是否發(fā)送成功了;? ? ? ? 但是每天請求能及時的收到正確的應答這個情況太理想了,實際上網絡傳輸數據可能會出現(后發(fā)先至--->一個數據包在進行傳輸的過程中走的路徑可能是非常復雜的.即不同的數據包,可能走不同的路線.)這樣的情況‘;
????????TCP在此處要完成兩個工作:
? ? ? ? 1、確保應答報文和發(fā)出去的數據, 能對上號,不要出現歧義
? ? ? ? 2、確保在出現后發(fā)先至的現象時,能夠讓應用程序這邊仍然按照正確的順序來理解數據
? ? ? ? 所謂的序號就是一個整數.大小關系,就描述了數據的先后順序,準確的說,序號不是按照"一條兩條"方式來進行編號的,而是按照字節(jié)來編號的,因為tcp是面向字節(jié)流的;
? ? ? ? 對于序列號并不是我們自己設定的,序列號的情況如下圖所示:
????????通過特殊的 ack 數據包,里面攜帶的"確認序號"告訴發(fā)送方,哪些數據已經被確認收到了
此時發(fā)送方,就心中有數了,就知道了自己剛發(fā)的數據是到了還是沒到.=>TCP 的初心,是為了實現可靠傳輸 =>達成可靠傳輸的最核心的機制, 就是確認應答? ? ? ? q1:如何區(qū)分一個數據包是普通的數據,還是 ack 應答數據呢?
????????
? ? ? ? q2:為啥確認序號是現在這樣的規(guī)則?即用收到的最后一個字節(jié)的序號+1來表示呢
? ? ? ? 主要是為了關聯后面的知識->滑動窗口,2、超時重傳
????????確認應答,描述的是一個比較理想的情況。但是如果網絡傳輸過程中,出現丟包,則發(fā)送方,勢必就無法收到 ACK 了,所以使用超時重傳機制,針對確認應答,進行補充.
????????為什么會丟包?
????????把網絡想象成公路,即錯綜復雜的公路網,在公路上就會有很多的收費站。平時車流量很通暢,但是當節(jié)假日的時候,收費站這里經常會堵車好幾個小時;
? ? ? ? 在網絡中,“收費站"可以理解成是一些路由器/交換機,如果數據包太多了,就會在這些路由器/交換機上出現"堵車",但是路由器針對“堵車”的處理,不會把這些積壓堵塞的數據包都保存好,而是會把其中的大部分數據包直接給丟棄掉.此時這個數據包就在網絡上消失了,????????真實的網絡環(huán)境,是錯綜復雜的,我們不會知道哪個節(jié)點上會出現上述"堵車"情況,也不知道啥時候會出現丟包, 丟包是非常隨機的事件.這個事情出現概率的大小,取決于網絡基礎設施施,同時也取決于網絡環(huán)境.
? ? ? ? 綜上所述,丟包是一個"隨機”的事件,因此在上述 tcp 傳輸過程中,丟包就存在兩種情況.
情況一:傳輸的數據丟了
情況二:返回的 ack 丟了
? ? ? ? 對于發(fā)送方的來說,無法區(qū)分這兩種情況.無論出現上述哪種情況,發(fā)送方都會進行"重新傳輸”第一次是丟了,重傳一下很大概率就能傳過去;重傳就是一個很好的丟包下的補救措施了
? ? ? ? q3:發(fā)送方,何時進行重傳?
? ? ? ? 引入等待時間,發(fā)送方發(fā)出去數據之后, 會等待一段時間, 如果這個時間之內, ack 來了,此時就自然視為數據到達;如果達到這個時間之后,數據還沒到,就會出發(fā)重傳機制
? ? ? ? q4:關于等待時間
? ? ? ? 1、初始的等待時間,是可配置的.不同的系統(tǒng)上都不一定一樣,也可以通過修改一些內核參數來引起這里的時間變化.
? ? ? ? 2、等待的時間,也會動態(tài)變化.每多經歷一次超時,等待時間都全變長(變長,隱含的含義,就是對能夠正確傳輸數據這件事,前面按照丟包概率 10% 計算,每次重傳一次都會讓傳輸成功的概率大幅度增加.)? ? ? ? eg:A->B發(fā)了一條數據,
????????第一次,A 等待 ACK 的時間,假設是 50ms,此時如果達到 50ms, 還沒有 ack,A 就重傳;
當 A 重傳的數據,還是沒有收到 ack,第二次等待的時間就會比第一次更長,拉長也不是無限拉長,重傳若干此時,時間拉長到一定程度,認為數據再怎么重傳也沒用了, 就放棄 tcp 連接(準確的說是會觸發(fā) tcp 的重置連接操作)? ? ? ? q5:關于接受端收到兩條一樣的數據的bug處理
????????其實 TCP 已經非常貼心的幫我們把這個問題解決了;TCP 會有一個"接收緩沖區(qū)",就是一個內存空間,會保存當前已經收到的數據,以及數據的序號;
????????接收方如果發(fā)現,當前發(fā)送方發(fā)來的數據,是已經在接收緩沖區(qū)中存在的 (收到過的重復
數據了),接收方就會直接把這個后來的數據給丟棄掉,確保應用程序進行 read 的時候,
讀到的是只有一條數據,? ? ? ? 所謂的接受緩沖區(qū),不僅僅是能進行去重,還能進行重新排序,確保發(fā)送的順序,和應用程序讀取的順序是一致的;
3、連接管理
? ? ? ? 即建立連接 + 斷開連接????????建立連接:
????????握手,只是為了喚起對方的注意,tcp 這里的握手,也是類似給對方傳輸一個簡短的,沒有業(yè)務數據的數據包,并通過這個數據包,來喚起對方的注意,從而觸發(fā)后續(xù)的操作.
????????TCP 的三次握手.TCP 在建立連接的過程中,需要通信雙方一共"打三次招呼”才能夠完成連接建立的,簡單分析圖如下所示:
????????A 想和 B 建立連接,A 就會主動發(fā)起握手操作;實際開發(fā)中,主動發(fā)起的一
方, 就是所謂的"客戶端,被動接受的一方,就是"服務器”(同步報文段,就也是一個特殊的 TCP 數據包,沒有載荷的 (不攜帶業(yè)務數據的))
? ? ? ? q6:三次握手是要解決什么問題?通過四次握手,是否可行?通過兩次握手,是否可行呢?
????????可以, 但是沒必要.兩個數據合并成一個數據效率更高.
? ? ? ? q7:三次握手核心作用:
1、確認當前網絡是否是暢通的,
2、要讓發(fā)送方和接收方都能確認自己的發(fā)送能力和接收能力均正常
3、讓通信雙方,在握于過程中,針對一些重要的參數進行協商
????????握手這里要協商的信息,其實是有好幾個的,至少大家要知道,tcp 通信過程中的序號從幾開始,就是雙方協商出來的(一般不是從1 開始的),每次連接建立的時候,都會協商出一個比較大的,和上次不太一樣的值.
????????這種設定方式,是避免“前朝的劍,斬本朝的官"----->
????????有的時候,網絡如果不太好,客戶端和服務器之間可能會連接斷開, 再重新建立連接;重連的時候, 就可能在新的連接好了之后,舊連接的數據姍姍來遲,這種遲到的數據,應該要丟棄掉的! 不應該讓這個之前的的數據影響到本次的業(yè)務邏輯~
????????如何區(qū)分數據是否是來自于上個朝代?就可以通過上述序號的設定規(guī)則來實現->如果發(fā)現收到的數據序號和當前正常數據的序號差異非常大就可以判定為是上個連接的數據就可以直接丟棄了;斷開連接,四次揮手:
????????建立連接,一般都是客戶端主動發(fā)起;斷開連接,客戶端和服務器都可以主動發(fā)起
? ? ? ? 四次揮手的簡單分析如下所示:
? ? ? ? q8:和 三次握手 不同,此處的四次揮手,能否把中間的兩次交互合二為一?不一定!!
????????不能合并的原因是因為ACK 和 第二個 FIN 的觸發(fā)時機是不同的.ACK 是內核響應的.B 收到 FIN,就會立即返回 ACK;第二個 FIN 是應用程序的代碼觸發(fā).B 這邊調用了 close 方法才會觸發(fā) FIN ->
????????從服務器收到 FIN(同時返回 ACK),再到執(zhí)行到 close發(fā)起 FIN,這中間要經歷多少時間,經歷多少代碼,是不確定的!!FIN 就會在 socket 對象 cose 的時候, 被發(fā)起.可能是手動調用 close 方法也可能是進程結束.故此綜上所述:
? ? ? ?象前面的三次握手, ACK 和 第二個 syn 都是內核觸發(fā)的.因為是同一個時機,可以合并;但是這里的四次揮手, ACK 是內核觸發(fā)的,第二個 FIN 是應用程序執(zhí)行 close 觸發(fā)的,二者的的觸發(fā)時機不相同,所以不能合并.
????????是否意味著,如果我這邊代碼 close 沒寫/沒執(zhí)行到,是不是第二個 FIN 就一直發(fā)不出去??(有可能的),并非所有的連接都是好聚好散;但是,TCP 中還有一個機制->延時應答,(后面再說),能夠拖延 ACK 的回應時間一旦 ACK 滯后了,就有機會和下一個 FIN 合并在一起了
????????
? ? ? ? q8:TIME_WAIT 狀態(tài)主要存在的意義?
????????如果最后一個 ACK 丟了,站在 B 的角度,B 就會觸發(fā)超時重傳重新把剛才的 FIN 給傳一遍,如果剛才 A 沒有 TIME WAIT 狀態(tài), 就意味著 A 這個時候就已經真的釋放連接了,此時重傳的 FIN 也就沒人能處理, 沒人能返回 ACK 了.B 永遠也收不到 ACK 了
? ? ? ? A這邊使用 TIME_WAIT 狀態(tài)進行等待,等待的這個時間,就是為了處理后續(xù) B 重傳的 FIN此時有重傳的 FIN 來了, 就可以繼續(xù)返回 ACK 了.B 這邊的重傳 FIN 才有意義.
? ? ? ? q9:TIME WAIT 等待多久呢?
ps:本篇的內容就到這里了,如果大家感興趣的話就請一鍵三連哦?。?!
? ? ? ?文章來源:http://www.zghlxwxcb.cn/news/detail-828025.html
????????文章來源地址http://www.zghlxwxcb.cn/news/detail-828025.html
到了這里,關于【Java EE初階十六】網絡原理(一)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!