目錄
2.3.1 將 HTTP 請求訊息交給協議堆疊
2.3.2 對較大的資料進行拆分
2.3.3 使用 ACK 號確認網路包已收到
2.3.4 根據網路包平均往返時間調整 ACK 號等待時間
2.3.5 使用視窗有效管理 ACK 號
2.3.6 ACK 與視窗的合并
2.3.7 接收 HTTP 回應訊息
2.3.1 將 HTTP 請求訊息交給協議堆疊
資料收發操作是從應用程式呼叫write 將要發送的資料交給協議堆疊開始的,
一次將多少資料交給協議堆疊是由應用程式自行決定的,因此如果一收到資料就馬上發送出去,就可能會發送大量的小包,導致網路效率下降,所以會將資料存放在內部的發送緩沖區中,積累到一定量再發送,積累多少資料由以下條件判斷:
1. 每個網路包能容納的資料長度,協議堆疊根據MTU(Maximum Transmission Unit,最大傳輸單元,)來判斷,在以太網中MTU一般是 1500 位元組,MTU包含頭部,減去頭部剩下的才是真正的資料長度,稱為MSS(Maximum Segment Size,最大分段大小),TCP頭部+IP頭部約為40位元組,因此以太網中MSS一般是1460位元組,如果TCP/IP增加加密引數等其他資訊,頭部會增加,

2.時間,如果每次都要等到資料長度達到MSS,會要等半天造成延遲,因此需要一個計數器,超過一定時間就發送,
以上兩者其實是互相矛盾的,長度優先則效率高,一次能發送更多的資料,但延遲也高,相反,時間優先延遲低但會造成效率低,如何平衡則看堆疊協議的開發者怎么寫的代碼,
應用程式在發送資料時也可以指定一些選項,比如不等待直接發,像瀏覽器這種會話型的應用程式就是這樣,
2.3.2 對較大的資料進行拆分
HTTP訊息一般比較短,一個網路包就夠,但提交表單,比如我想做編輯的這篇文章,幾千個字,那肯定是裝不下了,得進行拆分,這個時候就會按照MSS的長度為單位拆分發送,

2.3.3 使用 ACK 號確認網路包已收到
發送網路包之后需要確認對面有沒收到,原理如下:

首先,TCP 模塊在拆分資料時,會先算好每一塊資料相當于從頭開始的第幾個位元組,在發送時將這個資料寫在 TCP 頭部,,“序號”欄位就在這時派上了用場,發送資料的長度可以由接收方根據上面說的計算得到,
通過以上兩個資訊可以檢查有沒丟包,例如上次接收到了1460位元組,下次的包序號為1461則正常,為2921則丟包,接收方將接收到的資料長度加起來寫入TCP頭部的ACK號中發給發送方,同時將ACK位元設為1表示欄位有效,
但實際上序號不是從1開始的,以防通信程序被攻擊,這個序號初始值是隨機的,需要在收發資料之前告訴對面,通過在前面講連接時的SYN(Synchronize,同步)設為1時,同時設定序號欄位的值實作,
服務器向客戶端發資料也是一樣的原理,

在沒有確認之前,發送過的包會保存在發送緩沖區,如果對方沒有回傳某些包的ACK,則重發,因此,網卡、集線器、路由器都沒有錯誤補償機制,直接重發就好了,但當斷網等情況時,怎么重發都沒用,如果TCP嘗試重發幾次無效之后就會強制結束通信,向應用程式報錯,
2.3.4 根據網路包平均往返時間調整 ACK 號等待時間
ACK 號的等待時間稱作超時時間,
當網路傳輸繁忙時就會發生擁塞,ACK 號的回傳會變慢,這時我們就必須將等待時間設定得稍微長一點,否則可能已經重傳了包,前面的 ACK 號才到來,這樣就多了次重傳,本身網路就擁塞,這下就更堵了,
但如果等待的時間太長,又會導致真的需要重傳的包受到影響,所以重傳時間也需要衡量,因此,TCP采用動態調整等待時間的方法,TCP發資料時順便測量ACK號的回傳時間,回傳的慢則延長時間,回傳的快則縮短時間,
2.3.5 使用視窗有效管理 ACK 號

每發一個包等一個ACK再發一個等一個效率太低,因此采用滑動視窗的方式,等ACK的時候也一直發送包,但這樣可能導致接收方受不了,處理不過來,
當接收方的TCP收到包后,將資料存放到接識訓沖區,然后計算ACK,組裝資料傳給應用程式,如果還沒完成下一個包就到了,這個包也會存放到緩沖區,但緩沖區如果也塞滿了,也會溢位,后面的資料進不來,怎么解決呢?
首先,接收方告訴發送方自己最多能接收多少資料(稱為視窗大小,一般和接收方的緩沖區大小一致),發送方根據這個值對資料發送操作進行控制,這就是滑動視窗方式的基本思路,具體操作直接看圖,

2.3.6 ACK 與視窗的合并
更新視窗大小的時機應該是接收方從緩沖區中取出資料傳遞給應用程式的時候,
而當接收方收到資料時,如果確認內容沒有問題,就應該向發送方回傳 ACK號,因此我們可以認為收到資料之后馬上就應該進行這一操作,
這樣的話,每收到一個包,就需要向發送方分別發送 ACK 號和視窗更新這兩個單獨的包,效率下降,因此,接收方在發送 ACK 號和視窗更新時,并不會馬上把包發送出去,而是會等待一段時間,在這個程序中很有可能會出現其他的通知操作,這樣就可以把兩種通知合并在一個包里面發送了,比如應用程式連續請求了資料,連續發生了視窗更新,只要發送最后的結果即可,
2.3.7 接收 HTTP 回應訊息
瀏覽器接收web服務器的回應訊息也需要協議堆疊的參與,和發送資料一樣,接收資料也需要將資料暫存到接識訓沖區中,當協議堆疊嘗試將緩沖區中訴苦傳給應用程式時,可能因為回應訊息還沒回傳,接識訓沖區中并沒有資料,這時該任務就會被掛起,等回傳訊息到達之后再繼續,協議堆疊這時會去處理其他應用程式的作業,
本節完,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/297545.html
標籤:其他
