最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析NIO系列之TCP

 更新時間:2021年06月15日 09:31:37   作者:wier  
NIO即同步非阻塞式IO,它和傳統(tǒng)的BIO比較最大的區(qū)別在于在執(zhí)行accept、connect、read、write操作時是非阻塞的。很有利于實現(xiàn)用少量線程來處理多個客戶端請求,可以隨時讓線程切換所處理的客戶端,從而可以實現(xiàn)高并發(fā)服務器的開發(fā)

一、前言

在spring boot 2中,默認的web 容器是netty ,這說明“反應式” 容器已經(jīng)是大勢所趨,無論是go 語言的協(xié)從線程,還是java 基于reactor 線程模型,都是基于事件編程實現(xiàn)高并發(fā)的實例。

在介紹NIO之前有必要了解下TCP協(xié)議,因為目前多數(shù)應用都是給予應用層進行操作,導致隱藏了大量的網(wǎng)路細節(jié),知道這些細節(jié)以及原理對我們的問題排查很有益處。

二、TCP 特性

TCP 是一種面向連接的協(xié)議,它給用戶進程提供可靠的全雙工的字節(jié)流。確保數(shù)據(jù)包的可靠,有序,以及支持流量控制。關于TCP 為何要做這些,我們從以下幾個方面入手:

1.IP網(wǎng)絡層為何不保證數(shù)據(jù)包的可靠性

2.TCP協(xié)議如何保證包可達、有序

3.TCP協(xié)議如何支持流量控制

4.TCP幾種狀態(tài)以及應用

三、IP網(wǎng)絡層為何不保證數(shù)據(jù)包的可靠性

我們先看下OSI的網(wǎng)絡分層,在以下分層中,TCP 位于傳輸層,它保證的是協(xié)議的可靠性和連續(xù)性。具體的收發(fā)報是有底層的鏈路層以及物理層所決定的,所以TCP 所做的工作,也是基于底層的優(yōu)化和改進。

客戶端與服務器之間的通信使用應用協(xié)議,傳輸層的通信采用TCP協(xié)議,而TCP 協(xié)議又采用了更低的一層IP協(xié)議,IP則使用某種形式的數(shù)據(jù)鏈路層通信。

我們知道網(wǎng)絡的中的數(shù)據(jù),最終通過多個路由器連接傳送的。最底層的以太網(wǎng)協(xié)議規(guī)定了電子信號如何組成數(shù)據(jù)包,解決了局域網(wǎng)的點對點通信問題,但無法解決多個局域網(wǎng)的的互通問題。

而網(wǎng)絡層采用的IP協(xié)議,就是定義了一套自己的地址規(guī)則,主要解決尋址和路由的功能,根據(jù)對方的IP地址,尋找最佳路徑傳輸信息。局域網(wǎng)通過路由器連接,路由器基于IP協(xié)議,指導數(shù)據(jù)包向某個路由借口轉發(fā)。但IP協(xié)議不保證包一定到達以及完整性,特別是網(wǎng)絡擁堵的時候,會丟棄一些數(shù)據(jù)包,保證數(shù)據(jù)的傳送效率。

而保證數(shù)據(jù)包的完整、有序以及可靠,這就是TCP 協(xié)議要來做的事情了。

四、TCP 協(xié)議

4.1、TCP 包組成

很多網(wǎng)絡有一個最大傳送單元,它是鏈路層中的網(wǎng)絡對數(shù)據(jù)幀的一個限制,以以太網(wǎng)為例,MTU為1500個字節(jié)。一個IP數(shù)據(jù)報在以太網(wǎng)中 傳輸,如果它的長度大于該MTU值,就要進行分片傳輸,使得每片數(shù)據(jù)報的長度小于MTU。

另外一個數(shù)據(jù)包還包含頭信息,除了自己的Tcp包頭,還有IP 頭信息和以太網(wǎng)頭信息。IP 數(shù)據(jù)包在以太網(wǎng)數(shù)據(jù)包的負載里面,最少需要20字節(jié),所以 IP 數(shù)據(jù)包的負載最多為1480字節(jié)。

那么tcp的一個包大小是多少吶?

我們需要機遇MSS這個值來確定,MSS是TCP里的一個概念(首部的選項字段中)。MSS是TCP數(shù)據(jù)包每次能夠傳輸?shù)淖畲髷?shù)據(jù)分段,TCP報文段的長度大于MSS時,要進行分段傳輸。 如果不設置,則MSS的默認值就為536個字節(jié) 。也就是說一個tcp包的在500字節(jié)左右。

4.2、如何保證可靠性

上述也說了,底層的路由轉發(fā)包,并不保證包的可靠性以及有序性。

首先為了保證包的完整性,TCP 會基于MSS 為大于 MSS的包進行分包處理,默認MSS大小為563byte,其大小小于MUT,以防止在網(wǎng)絡層被分片處理。

其次增加SEQ和ACK,同時采用超時重發(fā)的機制來保證包的可靠性。

1)SEQ

為了保證有序性,TCP 為每個包編配一個Sequence number ,簡稱 SEQ 。以便接收的一方按照順序還原。萬一發(fā)生丟包,也可以知道丟失的是哪一個包。一般第一個包的編號是一個隨機數(shù),也可以從1開始。

2)ACK

那么有編號了,如何確保包一定到達?

基于ACK 進行確認。對于接收方來說,每次接受一個包必須返回ack信息,發(fā)送端從而確認這個包已經(jīng)傳送到。另外,接收方要對每一條報文做校驗。如果校驗發(fā)現(xiàn)出錯,則不發(fā)送確認報文,從而觸發(fā)發(fā)送方超時重傳。

ACK 包含以下信息:

  • 期待要收到下一個數(shù)據(jù)包的編號 next SEQ
  • 接收方的接收窗口的剩余容量

我們采用wiershark抓包一個oschina的包看下三次握手的數(shù)據(jù)。

我的本機ip:192.168.1.103

oschinaIp:116.211.174.177

三次握手過程:

1.me->osChina:syn=1 seq=x ack=0

2.osChina->me:syn=1 seq=y ack=x+1

3.me->osChina:seq=x+1 ack=y+1


1、me->osChina:syn=1 seq=0 ack=0

2、osChina->me:syn=1 seq=0 ack=0+1

3、me->osChina:seq=0+1 ack=0+1

對比一下三次握手的過程。

3)超時重傳

我們知道網(wǎng)絡極其不穩(wěn)定,數(shù)據(jù)包即便增加了SEQ和ACK,能夠保證其有序性,但依然保證丟包或者超時的問題。如果發(fā)送端發(fā)送數(shù)據(jù),或者接收端回復ACK的消息在網(wǎng)絡中丟失或者超時怎么處理?

RTO ,超時重傳時間。要知道包是否出現(xiàn)超時,需要有一個評估方式,而RTT是對一個給定連接的往返時間的測量。由于網(wǎng)絡流量的變化,這個時間會相應地發(fā)生改變,TCP需要跟蹤這些變化并動態(tài)調(diào)整超時時間RTO。

發(fā)送方如果一定時間內(nèi)沒收到報文的ACK,就認為該報文丟失在網(wǎng)絡中了,自動重發(fā)該報文。這種機制稱之為超時重傳。

在這期間,如果接收端的消息,由于丟失,接收端沒有收到ack 消息,發(fā)送端會向接收端重發(fā)這個包。如果因為超時原因,發(fā)送端在超時定時器之后收到了這個包的ack 信息,而且發(fā)送端已經(jīng)重復發(fā)送了這個消息,此時發(fā)送端不會處理,直接丟棄該ack 。而接收端接收到了之后會再次回復ack 信息。

五、流量控制

上述中我們知道了TCP協(xié)議可以保證數(shù)據(jù)的可靠性,但是也得兼顧效率。兼顧效率的話需要考慮以下三個方面:

1.支持批量發(fā)包

2.能夠基于網(wǎng)絡的狀況,支持擁堵控制

3.能夠了解接收端的狀況,防止接收端處理不過來

基于以上三個需求,做了以下處理。

5.1、滑動窗口

如果TCP 中的包,都需要發(fā)送一個確認一個的話,效率太低了,單次發(fā)送和確認一個包,雖然保證了可靠性,但無法保證其效率。此時需要一個批量發(fā)送和確認的方式,這就是滑動窗口所做的事情。

發(fā)送滑動窗口:

發(fā)送窗口從左向右移動在這個發(fā)送窗口之前的數(shù)據(jù)必然是已經(jīng)發(fā)送而且得到接收方確認的數(shù)據(jù)落在發(fā)送窗口之內(nèi)的數(shù)據(jù)是發(fā)送方可以發(fā)送的數(shù)據(jù)在發(fā)送窗口之后的數(shù)據(jù)是不能發(fā)送的數(shù)據(jù)。

如果發(fā)生超時或者丟失現(xiàn)象。那么有兩種解決方案:

1、回退N,丟失的包號之后所有包都重發(fā)

2、選擇重傳ARQ,只發(fā)丟失的,避免重復的(效率高,防止發(fā)送重復的)

滑動窗口還有一個作用是讓發(fā)送端知道接收端的處理狀況。假設TCP接收方的緩存已經(jīng)滿了,無法處理更多的,而發(fā)送方并不知道,每次會給對方告知當前滑動窗口的大小值 ,此時發(fā)送端就不會再發(fā)送數(shù)據(jù)了。

1.接收方接收到數(shù)據(jù)同樣馬上發(fā)送確認,但是同時對發(fā)送方宣布窗口大小為0。這樣發(fā)送方就暫時不會發(fā)送數(shù)據(jù)。

2.報文到達時不馬上發(fā)送確認,直到緩存有足夠的空間。這樣就可以避免發(fā)送方滑動窗口。但是這也存在一個問題,接收方延遲發(fā)送確認的時間不應該超過超時時間,如果過長會導致發(fā)送方誤以為數(shù)據(jù)丟失重新發(fā)送數(shù)據(jù)。

5.2、擁堵控制

我們知道網(wǎng)絡狀況有好友壞,好的時候,可以多發(fā)些包,壞的時候,如果發(fā)包速率不變的話,除了會加重網(wǎng)路負擔以外,還會造成包的過多丟失,除非更多的超時重發(fā),這無疑識降低了通信效率。

基于此,TCP通信雙方維護一個叫做擁塞窗口(cwnd,congesion window)的值,這個值取決于網(wǎng)絡中的擁塞率,發(fā)送方的發(fā)送窗口的值就等于擁塞窗口的大小。只要網(wǎng)絡中沒有出現(xiàn)擁塞,擁塞窗口的值就可以增大一些,這樣發(fā)送方可以發(fā)送到網(wǎng)絡中的數(shù)據(jù)就多一些。反之,擁塞窗口的值就減小,從而避免加劇網(wǎng)絡的擁塞率。

TCP目前擁塞控制主要有以下4種算法:

1.慢啟動

2.擁塞避免

3.快速重傳

4.快恢復

具體的算法實現(xiàn)方式就不再介紹了,大概實現(xiàn)的功能就是,基于當前的網(wǎng)絡狀況,找到一個合適的發(fā)送速率,防止給網(wǎng)絡造成過大的負擔。比如說慢啟動,就是開始的時候,發(fā)送得較慢,然后根據(jù)丟包的情況,調(diào)整速率:如果不丟包,就加快發(fā)送速度;如果丟包,就降低發(fā)送速度。

六、TCP 狀態(tài)

了解TCP的都知道,TCP 建立連接的時候,有三次握手,斷開鏈接的時候又四次握手交互。那么其中的狀態(tài)是有哪些?

上面的圖看著是不是太亂記不住,我們看看下面這張梳理一下,看看具體應用狀態(tài)。

從上面可以看到,連接建立成功的時候,其狀態(tài)是ESTABLISHED 的。當接受端的狀態(tài)為SYN—RECV的時候,表示接受端,已經(jīng)回復第二次握手信息了,等待發(fā)送端再次確認。如果網(wǎng)絡中遭受到大量的SYN 攻擊,會存在大量的SYN_RECV 狀態(tài)。此時可以定位這些問題IP ,通過防火墻過濾就能解決大量的假連接問題。

七、消失的連接——TIME_WAIT

在網(wǎng)絡中,某一端主動關閉而沒有通過四次握手關閉,此時tcp已經(jīng)建立的通道是否還在,多久會關閉?此時的TCP 狀態(tài)為TIME_WAIT ,可以想象,現(xiàn)實中經(jīng)常出現(xiàn)這種狀況,多數(shù)的關閉連接都是主動關閉而非通過協(xié)商通信關閉。那么此時關閉,若果再重連還能重連上之前的tcp 通道么,還是需要重現(xiàn)創(chuàng)建。

任何TCP實現(xiàn)必須為MSL選擇一個值,默認是2分鐘或者30秒,TIME_WAIT默認是2倍的MSL,持續(xù)時間在1-4分鐘之間。MSL是IP數(shù)據(jù)包能在網(wǎng)絡中存活的最長時間。

TIME_WAIT 存在的兩個理由:

1、可靠的實現(xiàn)TCP全雙工連接的終止

2、允許老的重復分節(jié)在網(wǎng)絡中消失

TCP必須防止某個連接的老的重復分組在該連接已經(jīng)終止后再現(xiàn),從而被誤解成屬于同一連接的化身,有time_wait 足夠長,是2倍的MSL的,那么足夠讓某個方向上的分組最多存活MSL秒就被丟棄。

從TIME_WAIT狀態(tài)到CLOSED狀態(tài),有一個超時設置,這個超時設置是 2*MSL(RFC793定義了MSL為2分鐘,Linux設置成了30s),如此超過了這個時間,當前的tcp通道就會被定義為關閉。

以上就是淺析NIO系列之TCP的詳細內(nèi)容,更多關于NIO TCP的資料請關注腳本之家其它相關文章!

相關文章

  • 解讀classpath讀取resources目錄下的文件

    解讀classpath讀取resources目錄下的文件

    這篇文章主要介紹了解讀classpath讀取resources目錄下的文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • java線程中synchronized和Lock區(qū)別及介紹

    java線程中synchronized和Lock區(qū)別及介紹

    這篇文章主要為大家介紹了java線程中synchronized和Lock區(qū)別及介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Java基本數(shù)據(jù)類型包裝類原理解析

    Java基本數(shù)據(jù)類型包裝類原理解析

    這篇文章主要介紹了Java基本數(shù)據(jù)類型包裝類原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • java實現(xiàn)停車場管理系統(tǒng)

    java實現(xiàn)停車場管理系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現(xiàn)停車場管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • eclipse下整合springboot和mybatis的方法步驟

    eclipse下整合springboot和mybatis的方法步驟

    這篇文章主要介紹了eclipse下整合springboot和mybatis的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • java+mysql實現(xiàn)圖書館管理系統(tǒng)實戰(zhàn)

    java+mysql實現(xiàn)圖書館管理系統(tǒng)實戰(zhàn)

    這篇文章主要為大家詳細介紹了java+mysql實現(xiàn)圖書館管理系統(tǒng)實戰(zhàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • java實現(xiàn)計算器功能

    java實現(xiàn)計算器功能

    這篇文章主要為大家詳細介紹了java實現(xiàn)計算器功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • Java for循環(huán)的妙用之雞兔同籠問題

    Java for循環(huán)的妙用之雞兔同籠問題

    這篇文章主要給大家介紹了關于Java for循環(huán)的妙用之雞兔同籠問題的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Java中字符串與日期轉換常見方法總結

    Java中字符串與日期轉換常見方法總結

    這篇文章主要給大家介紹了關于Java中字符串與日期轉換常見方法的相關資料,在Java編程中經(jīng)常需要將字符串表示的日期轉換為日期對象進行處理,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • IDEA 2020 無法啟動的解決辦法(啟動崩盤)附IDEA 2020 新功能

    IDEA 2020 無法啟動的解決辦法(啟動崩盤)附IDEA 2020 新功能

    這篇文章主要介紹了IDEA 2020 無法啟動的解決辦法(啟動崩盤)附IDEA 2020 新功能,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04

最新評論

金坛市| 怀仁县| 大洼县| 泸溪县| 柘荣县| 湄潭县| 紫云| 无棣县| 仪陇县| 彩票| 柘荣县| 湖州市| 三穗县| 黑山县| 额济纳旗| 西吉县| 沙雅县| 三原县| 蕉岭县| 和硕县| 和顺县| 淳化县| 沭阳县| 腾冲县| 荣昌县| 右玉县| 南皮县| 上蔡县| 安泽县| 土默特左旗| 贵南县| 蒲城县| 朔州市| 胶州市| 安泽县| 焦作市| 临清市| 南召县| 赤城县| 木兰县| 林口县|