(Linux網絡協議)網絡基礎(應用層、傳輸層)

應用層

直面程序員的一層,因爲應用程序時程序員自己寫的,因此應用層的協議都是程序員自己決定的。

自定製協議

程序員自己根據自己的應用特點,定義協議(數據的格式 / 數據的描述信息)
在這裏插入圖片描述
序列化:將各個數據對象按照指定的協議組織成爲持久化存儲 / 數據傳輸的二進制數據串。(json序列化、protobuf、二進制序列化)。
反序列化:將二進制數據串按照指定協議解析得到各個數據對象。

一個序列化方式的好壞有很多的評定標準:解析性能、傳輸性能等。

知名協議

HTTP協議:超文本傳輸協議,早期專門用於傳輸超文本數據html,但是隨着協議發展多元化,不限制數據格式。
網址- - -統一資源定位符:URL- - - 在網絡中唯一標記定位一個資源。

如何定位 - - - URL中包含的元素

協議方案名稱 : // 認證用戶名:認證密碼@服務器IP地址 : 服務器處理進程端口 / 請求的資源路徑?查詢字符串#片段標識符
http://username:[email protected]:80/index.html?name=dz&age=16#ch

服務器IP地址:我們看到的不一定是IP地址,也可能是一個域名,服務器的別名,通過域名解析服務器就能得到服務器IP地址;
服務器端口:web服務器默認http服務端口時80端口,默認不顯示;
/請求的資源路徑:資源在服務器上的路徑,這裏的 / 是http根目錄,但是是一個服務器上的相對根目錄,只是一個子目錄;
查詢字符串:客戶端提交給服務端的一些數據,由 key=val&key=val 形式的鍵值對組成;(查詢字符串中不能出現特殊字符,因爲URL中特殊字符都有特殊含義,提交的數據有特殊字符會造成歧義,若提交的數據中有特殊字符,則需要進行數據轉義)。

urlencode:url編碼,將特殊字節每一個字節轉化成16進制的數字字符,並且使用%前綴作爲轉義標識。(如 + -> %2b)
urldecode:url解碼,在url中遇到%,則認爲其後兩個字符需要轉義,將第一個字符轉換成數字乘以16(左移4位),加上第二個字符轉換的數字。
片段標識符:html中的一個標籤id,直接跳轉到頁面的某個位置。

HTTP協議實現

wireshark:網絡抓包工具,抓取流經網卡的所有數據流量(什麼包都能抓);
fiddler:瀏覽器的代理工具,通過代理實現數據抓包(專業的http抓包工具);

https就是加密後的http協議,若要抓取 https 的數據包,則需要進行配置
在這裏插入圖片描述

HTTP協議格式

請求

  • 首行:GET http://123.456.58.25/admin HTTP/1.1 ,以空格間隔包含三個要素,並且最終以 \r\n 作爲結尾;
    請求方法:GET/POST/HEAD/DELETE/CONNECT/PATCH/OPTIONS/TRACE
    GET- - - 請求實體資源,也可以通過url中查詢字符串向服務器提交數據,數據不安全,url長度有限制(各個服務器應用商的限制);
    POST - - - 主要用於向服務器提交數據,提交的數據在正文中; GET/POST:GET請求沒有正文,POST請求有正文;
    HEAD- - - 類似於GET,只是相較於GET,head只要響應頭部,而不響應正文;
    URL: http://123.456.58.25/admin
    協議版本: HTTP/1.1 - - - 0.9/1.0/1.1/2.0
    0.9:這時候的http僅用於傳輸html數據,只有GET請求方法,並且協議格式不完整;
    1.0:正是規定了http協議格式,增加了多種請求方法,並且支持了不同文件格式的數據流;
    1.1:在1.0的基礎上增加了更多請求方法和頭部描述信息,並且支持了長連接,管線化傳輸;
    2.0:採用二進制流傳輸,可以多路複用,並且允許服務端主動推送數據;
    短連接:http基於在傳輸層tcp實現通信,短連接指的是建立連接,發送一個請求,得到相應之後,則關閉連接;
    長連接:一次連接可以發送多條請求。
    在這裏插入圖片描述

  • 請求頭部:描述本次請求的關鍵字段信息,由key:val形式的鍵值對組成,並且爲每個鍵值對以\r\n作爲結尾 key:val\r\n key:val\r\n
    connection 控制長/短連接/ cache-Control緩存控制 / User-Agent 客戶端的屬性 / Accept 描述自己所能接收的數據屬性 / Content-Length描述正文長度 / Content -Type描述符正文數據類型 / Cookie(早期http是短連接通信,是一個無狀態協議,不會保存客戶端的狀態,每次訪問都需要進行登錄,因此引入了Cookie保存客戶端狀態);
    Cookie:可以帶有一些信息,持續在通信中描述客戶端的通信狀態,但是不夠安全;
    空行:間隔頭部與正文,\r\n;接收http數據的時候,當連續接收兩個\r\n (\r\n\r\n)的時候,則認爲頭部到此結束;
    先獲取完整頭部,通過頭部中的Content-Length獲取正文長度,然後獲取指定長度正文,通過這種方式每次獲取完整一條http請求數據
    正文:提交給服務端的數據

  • 響應

  • 首行:HTTP/1.1 303 See Other,包含三個要素,以空格進行間隔,以\r\n作爲結尾
    協議版本:0.9 / 1.0 / 1.1 / 2.0
    響應狀態碼:表示本次的請求服務端所作出的響應結果
    1xx:描述信息
    2xx:表示本次請求正確處理完畢,典型:200
    3xx:重定向,你請求的資源在另一個位置,要求客戶端重新請求新的位置,301(永久),302(臨時)
    4xx:表示客戶端請求錯誤,400(請求錯誤),404(請求的資源不存在)
    5xx:表示服務端錯誤;500(服務器內部錯誤),502(代理請求失敗/無效響應),504(代理請求超時)
    狀態碼描述:對狀態碼的描述信息,可以是官方文檔對應描述,也可以是自定義

  • 頭部:關於本次響應的一些關鍵字段描述信息,以key:val鍵值對組成,以\r\n作爲結尾
    Transfer-Encoding:實體正文的傳輸方式 / Expires:緩衝過期時間 / Location-3xx重定向的新位置
    Set-Cookie:服務端通過set-cookie向客戶端傳遞信息,會被保存在客戶端瀏覽器的cookie文件中
    Cookie:客戶端每次通信從cookie文件讀取數據通過cookie向服務端傳遞信息(維持客戶端狀態信息)
    cookie的使用不夠安全,因此使用Session搭配使用
    Session:會話,服務端會爲每個登錄的客戶端創建會話,在服務端描述一些會話信息(客戶端身份信息,狀態信息),保存在服務端,可以通過cookie將session id 返回給客戶端,客戶端每次通信都會通過cookie帶有自己的session id;
    cookie和session有什麼區別?
    答:cookie持續傳遞客戶端狀態信息的字段,cookie是保存在客戶端上的數據,用於持續與服務端進行信息統一的一種手段;session是一種會話的控制,服務端保存的會話信息包含客戶端的身份狀態信息,通過cookie/set-cookie傳遞的session id 進行客戶端的身份狀態識別

協議的特性總是影響着上層程序的編寫,而協議的特性又來源於協議的實現

傳輸層

負責應用程序之間的數據傳輸(通過端口的描述- - -描述哪兩個進程在進行通信)- - - UDP/TCP

UDP:無連接,不可靠,面向數據報

udp協議報頭只有8個字節
在這裏插入圖片描述
無連接:不需要建立連接,只要知道對方的地址信息就能直接發送數據;
不可靠:udp在傳輸層不保證數據安全有序到達對端,需要程序員在應用層進行包序管理;
面向數據報:有最大長度限制的傳輸方式,取決於數據報長度字段,因爲長度字段只有16位,因此數據報總長度不能大於64k,也就是說sendto接口給予的數據長度不大於64k-8k(報頭佔8個字節);
因此若傳輸的數據比較大,則需要程序員在應用層進行分包操作,並且進行包序管理

udp通信在報頭中確定了數據報長度,因此udp的數據傳輸是整條收發的
發送:sendto給予的數據放到發送緩衝區後就會直接封裝頭部,進行發送
接收:recvfrom 總是隻能接收一條完整的數據,而不會出現接收半條或者多條的情況
因此recvfrom 給予的緩衝區一定要足夠大,若給予的緩衝區大小小於一條數據的長度,則recvfrom就會報錯(因爲udp無法交付半條數據);

TCP協議:面向連接,可靠傳輸,面向字節流

在這裏插入圖片描述
面向連接:連接建立成功之後才能進行數據通信,tcp 有自己的連接管理(三次握手建立連接/四次揮手斷開連接);
在這裏插入圖片描述

爲什麼握手是三次?揮手是四次?
答:因爲2次不安全,4次沒必要;tcp通信需要確保雙方都具有數據收發的能力,因此雙方都發送SYN確保對方具有通信能力;四次揮手:發送FIN包,只能表示對方不再發送數據了,不表示對方不再接受數據,因此被關閉方進行ACK回覆之後有可能還會繼續發送數據,等到不再發送數據了,纔會發送下一個FIN包,因此FIN和ACK是分開的。

TIME_WAIT狀態有什麼用,爲什麼主動關閉方法沒有直接進入close釋放資源?
假定主動關閉方最後一次的ACK丟失,被動關閉方法沒有收到最後一次ACK,超時後就會重傳一個FIN;假定客戶端沒有TIME_WAIT 直接釋放資源,就可能啓動新的客戶端使用與之前客戶端相同的地址信息。

  • 1、剛啓動新的客戶端綁定地址成功,收到重傳的FIN包,對新連接造成影響;
  • 2、新啓動的客戶端,若是向相同的服務端發送SYN,因爲服務端處於LAST_ACK要求的是ACK而不是SYN,因此就會發送RST;
    因此若主動關閉方最後一次回覆後直接釋放資源,就有可能會對新啓動的新連接造成影響,因此必須等待一段時間,能夠處理有可能重傳的FIN。
    等待的時間多長比較合適:2個MSL時間 - - - MSL(報文最大生存週期);
    1.處理重複的FIN包 / 2.等待本次通信的所有報文都消失在網絡中,避免對新連接造成影響;

tcp三次握手失敗,服務端是如何處理的?

  • 1、沒有收到SYN,什麼都不做
  • 2、回覆了SYN+ACK但是,長時間沒有收到響應,則超時後發送RST重置連接報文,釋放資源;

一臺主機上出現大量的TIME_WAIT是什麼原因?如何處理?

  • TIME_WAIT是主動關閉方出現的,一臺主機出現大量的TIME_WAIT 證明這臺主機上大量的主動關閉了連接,常見於一些爬蟲服務器。
  • 處理:
    1、調整TIME_WAIT等待時間,也可以使用開啓地址重用的套接字選項 - setsockopt/
    2、地址重用:允許套接字綁定使用中的地址端口,常用於防止socket處於TIME_WAIT無法使用相同地址信息進行綁定新的套接字。

一臺主機上出現大量的CLOSE_WAIT是什麼原因?如何處理?

  • CLOSE_WAIT是被動關閉方收到FIN請求進行回覆之後的狀態,等待上層程序進行進一步處理,若出現大量CLOSE_WAIT,有可能是被動關閉方主機上程序中忘了最後一步斷開連接後調用close釋放資源;

tcp連接管理中的保活機制

tcp通信中,若兩端長時間沒有數據往來,則這段時候每隔一段時間,服務端向客戶端發送一個保活探測數據報,要求客戶端進行回覆,若連接多次沒有收到響應,則認爲連接斷開。

長時間沒有數據往來:默認7200s,可通過設置套接字選項進行配置;
每隔一段時間:默認75s,可通過設置套接字選項配置;
連續多次無響應:默認9次,可通過設置套接字選項設置;
連接斷開對接收端的影響:recv會返回0 ;
連接斷開對發送端的影響:send觸發異常 - - - SIGPIPE

可靠傳輸

  • 1、面向連接
  • 2、確認應答機制,發送數據後要求對方進行確認回覆,才能知道對方是否收到了這條數據,通過序號與確認序號實現;
  • 3、超時重傳機制,發送數據等待卻響應超時之後(默認一般在200ms左右),認爲數據丟失,則進行重新傳輸;
  • 4、通過序號/確認序號字段實現數據有序交付
  • 5、通過校驗和字段校驗數據一致性,不一致則要求對方進行重傳;

在這裏插入圖片描述
seq:本次數據的起始序號;
ack:對方發送數據的確認序號,告訴對方確認序號之前的數據我收到了;

  • 三次握手時,雙方會協商起始序號(上圖中是從0開始,但是實際中可能是一個隨機值),三次握手中,雖然數據長度爲0,但是確認序號是對方發送的起始數據序號+1;
  • 數據通信時,確認序號是對方發送數據中的起始序號加上數據長度,告訴對方這個確認序號之前的數據都已經收到了;(這麼做的目的是爲了防止因爲確認回覆的丟失而導致的重傳)
    就算是因爲網絡原因,後發的數據先到了,接收方也會根據協商的起始序號,根據每條數據中的起始序號,將數據在接收緩衝區中進行排序;

避免因爲一些原因導致丟包

1、額外的丟包問題處理

  • 1、發送方發送數據過快,接收方來不及處理取出,接收緩衝區滿溢,則以後的數據都會被丟棄;
  • 2、發送方發送大量數據,但是因爲網絡狀態不好導致大量丟包造成重傳;

2、滑動窗口機制:依靠協議中的窗口大小字段實現流量控制
接收方通過協議中的窗口大小字段,告訴發送方,最多可以發送多少數據(窗口大小不大於接收方緩衝區剩餘空間大小);
MSS:最大數據段大小,表示tcp數據通信時一條數據的最大大小,通信時雙方進行協商,取雙方MSS中較小的一方作爲最大數據段大小;
在這裏插入圖片描述
在這裏插入圖片描述
滑動窗口在發送方維護髮送窗口 / 接收方維護接收窗口 - - -窗口通過一個後沿序號 / 前沿序號實現
窗口大小不能大於接收方的接收緩衝區中剩餘空間的大小 - - - 避免了發送的數據太多而緩衝區滿了沒處放導致的丟包;

發送窗口:表示一次最多從後沿到前沿發送多少數據,不超過接收方窗口大小;

  • 後沿:所要發送數據的起始序號,後沿的移動取決於能否收到數據確認回覆;
  • 前沿:根據接收方窗口大小計算的結束序號,取決於接收方響應的窗口大小(前沿減去後沿的大小就等於接收方的窗口大小);

接收窗口:表示從哪裏開始接收數據,接收到多少序號爲止,不超過剩餘空間大小(進行包序管理,哪個包應該放在緩衝區的什麼位置)

  • 後沿:接收數據是起始序號,後沿的移動決定於是否收到了後沿的數據;
  • 前沿:根據接收緩衝區剩餘空間大小計算得到的接收的數據的結束序號,前沿的移動取決於緩衝區中剩餘空間大小。

滑動窗口機制允許發送端根據窗口大小以及mms連續發送多條數據,一旦丟包:

  • 停等協議:得到一條回覆,然後才能發送下一條數據;
  • 回退n步協議:一條數據丟失了,則需要發送端將丟失的這條數據以後的數據都進行重傳;
  • 選擇重傳協議:一條數據丟失了,則僅僅針對丟失的這條數據進行重傳;
    因爲網絡狀態不好,導致發送的數據越多丟包的越多:擁塞控制
    擁塞控制:進行網絡探測,以一種慢啓動、快增長的傳輸方式,進行根據網絡狀態調整發送速度的機制;

提高傳輸性能的方式

  • 快速重傳機制:發送端連續發送多條數據,若接收端接收數據並非是接收後沿數據,則認爲有可能後沿數據丟失了,首先不會接收到數據的確認回覆,其次向發送間隔連續發送三次後沿數據的重傳請求,要求對方對後沿數據進行重傳;
    發送方連續收到三條同一重傳請求,則對這條數據進行重傳

爲什麼是三次:避免因爲網絡延遲,數據報的延遲到達,三次可以有一個緩衝時間,若在第二次的時候收到了後沿數據報,則不再發送第三條重傳請求,這時候發送端也就不用重傳了;
快速重傳可以一定程度避免發送端必須的超時重傳;

  • 延遲應答機制:接收方接收到數據之後,並不立即進行確認回覆(因爲如果立即進行確認回覆,接收緩衝區剩餘空間變小了,窗口就變小了,導致傳輸的吞吐量變小),而是延遲應答,則有可能應答的時候程序上層已經將數據取出,保證窗口大小不會變小。
  • 捎帶應答機制:接收方接收到數據之後,進行確認回覆,確認回覆就是一個報頭中的確認序號進行的,爲了減少空報頭的響應占據帶寬,則使用捎帶應答,在即將發送的數據頭部中進行上一條接收到的數據的確認回覆。

可靠傳輸實現:面向連接 / 確認應答 / 超時重傳 / 序號 / 確認序號 / 校驗和
避免丟包重傳:滑動窗口機制 / 擁塞機制
挽救傳輸性能:快速重傳 / 延遲應答 / 捎帶應答 / 延遲發送

面向字節流:字節流傳輸服務- - -面向連接的,有序的一種最小以字節爲傳輸單元的傳輸方式;

  • 發送端在send發送數據的時候,並不會立即封裝報頭,而是將數據先放到發送緩衝中,選擇合適的時候再去從緩衝區中取出合適大小的數據進行傳輸;
  • 接收端在recv接收數據的時候,並非一條一條向上交付,而是根據recv想要的數據長度從接收緩衝區中取出指定長度的數據進行交付;
  • 優點:傳輸比較靈活,大量小的數據會集合成一條大的數據進行一次性傳輸,減少了IO次數,提高性能(延遲發送可以關閉,可配置的),接收方接收也更加靈活,想要多少取多少;
  • 缺點:tcp交付的這條數據可能並非一條完整的數據,也有可能是多條數據,(tcp對於上層給予的數據邊界並不敏感,不關注是幾條數據,只關注自己可以傳輸多少字節的數據 / recv 想要多少字節的數據 - - - 反之udp對每條數據有邊界區分,每次剛好就只交付一條完整的數據),導致上層將多條數據當做一條數據進行處理。
tcp粘包問題

tcp有可能將多條數據當做一條數據進行處理(udp是不會出現粘包問題的,因爲udp頭部中定義了數據報長度)

粘包的解決方案(程序員在應用層進行數據的邊界管理)

  • 1.每條數據之間以特殊字符進行間隔 - - - 缺陷:如果數據中有這個特殊字符,就需要進行轉義處理;
  • 2.數據定長傳輸 - - - 缺陷:數據短小的情況下進行補位,傳輸了大量的無用數據;
  • 3.應用層協議頭部中定義數據長度 - - -http / udp
    http如何解決粘包的:http頭部以 \r\n\r\n 特殊字符間隔表示結束,並且在頭部中通過Content-Length確定正文長度;
    udp如何解決粘包的:在傳輸層就進行了粘包的解決,頭部定長8字節,頭部中定義數據報長度;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章