TCP(UDP)/IP 作為網絡通訊協定最基礎和常用的協定, 讨論的非常多, 本文對TCP/IP 做一個簡單的回顧
1、網絡協定模型
鍊路層 (對應的是硬體部分, 在 7層模型中對應 鍊路層和實體層)
網絡層 IP協定所在的層 (7 層模型中的 網絡層)
傳輸層 TCP協定所在的層 ( 7 層模型的 傳輸層)
應用層 HTTP、FTP 協定所在的層 ( 7 層模型上三層)
其實層次模型非常好記, 最底層肯定是要處理硬體的轉換; 接着就是需要尋址, 裝置互聯; 連通了裝置, 考慮資料發送的各種(比如 流量控制);最後在這個基礎上可以設計任意協定。
這也給了我們 在設計程式 互動的思路、平台架構的思路,先基礎設施、然後功能疊加。
2、TCP 建鍊(握手)過程 和 關閉連結(揮手)過程
TCP 三次握手
Client A sync=j ->Server B 進入SYN_SEND狀态
Server B sync=j+1 sync=k - >Client A 進入SYN_RECV 狀态
Client A sync=k+1 ->Server B 共同進入 ESTABLISHED狀态
TCP 四次揮手
Client A Fin(i) -> Server B
Server B Ack(i+1) -> Client A
Server B Fin(j) - > Client A
Client A Ack(j+1) -> Server B
關閉時,采用四次而不是三次,因為A關閉時,此時 B 不一定資料都發完了,是以B要另外等一下再發自己的關閉消息
3、IP 路由過程
從前面的描述,可以知道 每一層協定都會在消息頭部加上自己的内容, 比如TCP層加上端口号, IP層會加上IP位址, 鍊路層則會加上MAC位址。
那通訊的兩個節點 A 怎麼知道 如何到 B呢?
I、網段内的路由 - ARP
對于 一層裝置(HUB)組合的網絡, 不能識别IP和MAC都是廣播的。
對于 二層裝置(交換機)組合的網絡。
a、A 發出廣播, 尋找目标IP的 MAC位址, 并附上自己的MAC位址。
b、交換機收到廣播, [更新自己的MAC位址表], 轉發廣播請求
c、B收到廣播響應消息, 給A回一個消息
d、交換機收到消息 , [更新自己的MAC位址表], 找到A 的MAC位址對應的端口,把消息給A
e、A收到消息, 得到B的MAC位址, 緩存在本地。 尋址結束
II、不同網段的路由 - RIP/BGP
如果是跨網段的路由, 則需要用到 三層交換裝置(路由器), 識别IP位址
尋址過程和 交換機的類似, 隻是中間過程, 路由器需要不斷的接力, 把資料在 路由器網絡間傳遞, 到達目标網段後, 再由目前路由器分發到具體的節點(通過查找ARP緩存或者廣播ARP消息)
路由器之間的 路由過程?
通過IP 和 掩碼建構路由表。這個路由的構成, 就是通過 RIP協定廣播得到的。
a、每隔一段時間 廣播一下自己的路由表;為了防止廣播風暴, 時間間隔可以設定随機
b、收到的路由器更新自己的路由表
c、防止路由互相更新循環錯誤, 規定最大不能超過 15跳(每經過一個路由器, 為一跳),超過 15跳, 認為路徑不可達
4、資料發送
I、發送内容
a、IP封包
b、TCP 封包
c、UDP 封包
IP封包的資料段就是TCP/UDP封包, 理論上一個IP封包的最大單包大小可達 65535(包含封包頭), 實際上因為在傳輸過程中 會對IP包分片為 MTU;而以太網的MTU值為 1500;實際使用中, 一般單包長度設定 < 1500 - 20(IP頭) - 20(TCP頭)
可以使用 Wireshark 抓包看每個封包, 網絡程式開發時, 檢視封包是非常重要的手段。
重點關注 封包内容| 封包長度 | 五元組(源和目标的IP位址、端口, 協定類型)
II、流量(擁塞)控制 - 滑動視窗協定
傳輸的雙方非常類似于傳統的 生産-消費模型;發送方就是 生産者,接收方就是 消費者。
在生産 - 消費模型的典型設計中, 一般會有一個 緩存隊列, 生産者不斷推送資料到隊列,消費者不斷從隊列取資料進行處理。當兩者的處理速率不一緻時, 就會出現 要麼隊列充滿, 生産者等待, 要麼隊列為空, 消費者等待。
滑動視窗協定也采用了類似的思路。
在發送方和消費方都有各自的緩存 - 類似于 隊列。
a、在建鍊時, 協商每次發送的資料大小 (視窗 window); 以後每次接收方都回報一個 視窗通知, 告知可接受的視窗大小; 如果為 0 , 發送者停止發送
b、發送方和接收方不斷調整視窗的大小, 當出現擁塞時, 發送方減小視窗大小; 如果接收方處理加快,則視窗也加大
這樣就實作了 動态調整 高效的 資料發送和接受
III、TCP VS UDP
TCP是面向連接配接的協定, 通過封包, 可以看到 TCP 有确認措施, 保證資料能夠安全發送和接受, 沒有确認的, 會重發; 通過流量控制的視窗, 可以保證 資料有序的發送.
UDP是無連接配接的協定, 通過封包可知, 發送方隻管發送, 不管是否收到, 也不管順序。 但因為, 缺少互動的确認過程, 是以 UDP 的發送效率要高于TCP。
一般情況下, 如果需要更高效率的發送可以使用UDP, 而且UDP并沒有想象的有那麼多丢包。 實際使用過程中, 可以由應用, 在資料裡面增加 資料序号, 進而實作丢包重發和排序。