目錄
一、再談埠號
1、埠號范圍劃分
2、相關指令
二、UDP協議
1、udp協議格式
2、udp的特點
4、udp使用注意事項及基于udp的應用層協議
三、TCP協議
1、tcp協議格式
2、tcp報頭解釋
3、TCP確認應答機制
4、TCP超時重傳機制
5、tcp三次握手四次揮手
6、滑動視窗
7、流量控制
8、擁塞控制
一、再談埠號
埠號用來唯一標識一臺主機上通信的行程,在tcp協議中用“源ip”、“源埠”、“目的IP”、“目的埠”、“協議號”這樣一個五元組來標識一個通信,

1、埠號范圍劃分
-
0 - 1023: 知名埠號 , HTTP, FTP, SSH 等這些廣為使用的應用層協議 , 他們的埠號都是固定的 .
-
1024 - 65535: 作業系統動態分配的埠號. 客戶端程式的埠號, 就是由作業系統從這個范圍分配的.
一些知名埠號:
- ssh服務器使用22號埠號;
- ftp服務器使用21號埠號
- telnet使用23號埠號
- http使用80埠號
- https使用443埠號
2、相關指令
1)查看知名埠號
cat /etc/services
2)netstat查看網路狀況
netstat選項
- n:拒絕顯示別名,能顯示數字的全部轉化成數字,
- l:列出所有在listen服務狀態
- p:顯示建立相關鏈接的程式名
- t:只顯示tcp相關選項
- u:只顯示udp相關選項
- a:顯示所有選項,默認不顯示listen相關
3)查看服務器的行程id--pidof
pidof 行程名
思考1:一個行程可以bind多個埠號?
可以,一個行程可以系結多個埠號,通過這些埠號都可以找到這個行程,
思考2:一個埠號可以被多個行程bind?
不可以,埠號的作用是唯一標識一臺主機上的具體某一個行程,如果多個行程都系結一個埠號就失去了埠號的意義,
二、UDP協議
用戶資料報協議(udp)是作業在傳輸層的一個重要協議,UDP 為應用程式提供了一種無需建立連接就可以發送封裝的 IP 資料包的方法,
1、udp協議格式

思考1:上層協議是如何將udp協議的報頭和有效載荷(資料)分離?
udp的報頭是一個8位元組的定長報頭,當拿到一個udp資料報是讀取到的前8個位元組就是報頭,報頭中包含一個16位的udp長度欄位,通過該欄位計算出udp有效載荷大小,這樣就將udp報頭和有效載荷成功分離,
思考2:udp協議最多可以傳送多少資料?
注意:16位udp長度可以認為是一個unsigned型別,且16位udp長度包括報頭的8位元組,
16位udp長度最多可以表示65535個位元組,而報頭占8位元組,因此udp有效載荷最大長度為65535-8=65527位元組,
思考3:udp協議如何保證用戶資料報的完整性?
udp稱為用戶資料報協議,因此一定要保證用戶資料報的完整性,具體做法就是8位元組報頭+16位丷長度來計算有效載荷長度,從而確保上層協議拿到的是一個完整的資料報,
思考4:16位檢驗和有什么作用?
udp是一個無連接不可靠的傳輸層協議,它的檢驗和只是用來檢驗資料本身是否出錯,由于udp的不可靠性,一旦檢測到檢驗和出錯,udp協議直接將該資料包丟棄,
總結:udp協議通過協議包頭中的16位的源埠和16位的目的埠直到自己“從哪來,到哪去”,通過16位udp長度直到自己攜帶了多大的資料報,并且可以通過這16位udp長度將報頭和有效載荷進行分離,還有一個16位的檢驗和,用來驗證資料報是否出錯,如果出錯直接丟棄,
2、udp的特點
udp協議有以下三個主要特點:
- 無連接:直到對端的IP地址和埠號就可以直接進行傳輸,不需要建立連接,
- 不可靠:沒有確認機制,沒有重傳機制,如果因為網路原因導致資料丟失等,udp協議層也不給應用層回傳任何資訊,
- 面向資料報:傳輸的資料的單位是資料報,
- 由于udp是面向資料報的,就導致udp不能靈活的控制資料的傳輸和接收次數,udp交給應用層的報文udp就原樣發送既不會拆分也不會合并,也就是說,應用層交給udp100個位元組的資料,udp一次就傳輸100個位元組的資料,接收端也必須一次接收完100個位元組的資料,
其次udp還有以下特點:
- udp的socket是全雙工的(同一時間既能讀取資料也能寫入資料)
- udp沒有真正意義的發送緩沖區但是具有接識訓沖區,
udp的緩沖區:
udp是全雙工的,同一時間可以同時進行讀和寫資料,但是如果資料量較大時就有可能導致資料處理不過來,因此需要緩沖區將資料存起來,
- udp沒有真正意義的發送緩沖區,呼叫sendto會直接交給內核, 由內核將資料傳給網路層協議進行后續的傳輸動作
- udp具有接識訓沖區,但是這個接識訓沖區不能保證收到的UDP報的順序和發送UDP報的順序一致; 并且如果緩沖區滿了, 再到達的UDP資料就會被丟棄,
4、udp使用注意事項及基于udp的應用層協議
udp可以傳輸的資料大小為2^16位元組(64k),在當今的互聯網環境下是一個非常小的數字,因此如果需要傳送大于64k的資料就需要在應用層手動分包多次發送,并在接收端手動拼接,
基于udp的應用層協議:
- NFS: 網路檔案系統
- TFTP: 簡單檔案傳輸協議
- DHCP: 動態主機配置協議
- BOOTP: 啟動協議(用于無盤設備啟動)
- DNS: 域名決議協議
三、TCP協議
TCP全稱為傳輸控制協議,主要功能是對資料的傳輸進行詳細的控制,
1、tcp協議格式

tcp協議的報頭是不定長的,報頭的首部有一個4位欄位表示報頭的長度,具體表示的是該tcp 報頭有多少個32bit(4位元組),也就是說規定了tcp報頭最大長度為(2^4-1)*4 = 60位元組,由于tcp傳輸的是位元組流,因此tcp的有效載荷可以是任意長度的,
同樣的,頭部8個位元組源埠和8個位元組目的埠表示資料“從哪來到哪去”,由于tcp是面向連接的可靠傳輸,因此在tcp的頭部還有很多欄位用來確保資料的可靠傳輸(后面詳細講),
2、tcp報頭解釋
- 源埠:表示發送資料的行程
- 目的埠:接收資料的行程
- 32位序號:發送的資料的序號
- 32位確認序號:接收到的資料的確認號(一般為序號+1)
- 4位首部長度:表示tcp首部長度(20~60位元組)
- 6位標志位
URG:緊急指標是否有效
ACK:確認號是否有效
PSH:當接收端緩沖區滿時,且一直沒有拿走資料,發送端會發送一個PSH標志位為1的資料,提示接收端應用快速將緩沖區的資料取走,
PST:重新建立連接,攜帶PST標志位的報文稱為復位報文段,
SYN:請求建立連接,攜帶SYN標志位的報文稱為同步報文段,
FIN:關閉連接,攜帶FIN標志位的報文稱為結束報文段,
- 16位視窗大小:接收端的緩沖區大小是有限的,給接收端發送資料將接識訓沖區填滿后如果在繼續發送,則會將原來的資料覆寫,因此tcp協議會將自己的接識訓沖區的剩余大小保存在16位視窗大小中和資料一起發送過去,需要注意的是,在tcp進行三次握手時就會進行第一次視窗大小的“協商”,
- 16位校驗和:發送端填充, CRC校驗. 接收端校驗不通過, 則認為資料有問題. 此處的檢驗和不光包含TCP首部, 也包含TCP資料部分.
- 16位緊急指標:標識哪部分資料是緊急資料,
3、TCP確認應答機制
tcp進行的是可靠傳輸,傳輸的是位元組流,因此,對于tcp協議需要做到以下兩點:①確保接收端成功接收到資料②確保接收端接收到資料的有序性,
網路中存在許多復雜的情況,因此并不能保證接收端接收到的資料的順序就是發送端發送的順序,因此tcp協議需要確保接收端接收到資料后能夠按照正確的順序對資料進行處理,
確認應答機制:發送方每發送一個資料,接收方就要向發送方發送一個確認信號,表明自己已經收到該資料,從而確保接收端成功接收到資料,

思考:tcp 是如何實作確認應答機制并且確保接收到的資料的順序的?
在tcp報頭中,有兩個4位元組的欄位,分別表示的是32位序號和32位確認序號,tcp協議對將每個位元組的資料都進行了編號,這個編號就是序號,在發送資料時會將資料的編號放在報頭的32位序號中一起發送過去,接收端接收到資料后會發送一個包含32位確認序號的資料,32位確認序號表示的意思是已經接受度奧x號資料期望收到x+1號資料,例如,上圖中發送端發送1~1000號資料,接收端接收到會給發送端發送確認號為1001的確認資料,表示自己已將將1000之前的所有資料都接收到了,希望下次接收到的是1001號資料,這樣,tcp協議就完美的實作了確認應答機制,同時tcp協議還可以通過32位序號將接收到的序號按照發送順序進行處理,保證資料的順序不會出錯,

注意:確認應答機制永遠也不能對所有的資料進行確認,總是會有最后一條資料無法確認,因此確認應答機制并不對確認資料進行確認,
4、TCP超時重傳機制
tcp協議在保證資料可靠傳輸是,還需要確保丟失的資料能夠重新發送,因為,在主機A發送給主機B的資料可能由于網路原因導致資料發送失敗,因此主機A也就收不到主機B的確認,在tcp協議中,如果主機A給主機B發送一個資料,在規定時間內主機A沒有收到資料B的確認,主機A 就認為該資料丟失了(實際上不一定是丟失了,有可能是網路擁堵資料正在發送),會將該資料重新發送給主機B,這就是超時重傳機制,

無論是資料發送失敗(接收端確實沒有接收到資料),還是資料還沒發送過去或者只是確認資料發生丟包(接收端接收到了資料),一旦超時發送端都會將該資料重新進行發送,那么一定會導致接收端存在很多重復的資料,那么該如何設定超時時間呢?
最理想的情況就是找一個最小時間,確保資料在這個時間內一定能夠到達,但是這個時間的長短隨著網路環境的變化,是不同的,如果時間設定過長會影響傳輸速率,如果時間設定過短有可能會頻繁發送重復的包,
TCP為了保證無論在任何情況下都能比較高性能的通信,會動態計算這個時間,在linux中超時時間以500ms為一個單位,每次判斷超時重發的時間都是500ms的整數倍,如果重發一次仍然得不到應答,會等待500*2ms后進行重傳,如果還是不能得到應答則在等待4*500ms重發,以此類推,當累計到一定次數,tcp會認為對端或者網路出現例外,直接強制斷開連接,
5、tcp三次握手四次揮手

三次握手程序
1)如何理解連接
對于服務器來說,服務器是1對多的,一個服務器可能要被很多個客戶端連接,因此,服務器端需要將眾多的連接進行管理,這就導致服務器得為這些連接建立相應的資料結構,同時這些操作也是需要時間的,所以,建立連接是需要時間+空間代價的,
2)三次握手程序
- 一般情況下,第一次連接請求是由客戶端主動發送的,
- 客戶端向服務器發送一個SYN請求,并將自己置為SYN_SENT狀態,阻塞等待服務器的應答,
- 服務器收到客戶端的請求后,會向服務器端發送一個SYN+ACK資料包,表示服務器端收到客戶端的請求,并且向客戶端也發起連接請求,此時,服務器端變為SYN_RCVD,等待客戶端的確認,
- 客戶端收到服務器端的SYN+ACK資料包后會再次向服務器端發送一個ACK確認資料包,發送成功后客戶端置為ESTABLISHED狀態,并且認為已經連接成功,
- 當服務器端收到客戶端的ACK確認后,此時雙方建立連接成功,服務器置為ESTABLISHED狀態,
3)為什么是三次握手?
- 如果是1次握手,客戶端給服務器端發送一個連接請求直接就連接成功了,這與udp五連接有什么區別?建立連接是為了更好的管理,一次握手建立連接很容易遭到黑客的SYN洪水攻擊,導致服務器宕機,
- 如果是2次握手,客戶端向服務器端發送一個請求,服務器端向客戶端發送一個確認,到此請求建立成功,那么存在一個問題,服務器端發送的ACK確認如果丟失了,此時服務器認為已經建立連接成功了,而客戶端沒有收到服務器的ACK確認認為沒有建立連接成功,就會進行超時重傳,這樣就可能導致服務器端資源浪費,同時2次握手也容易遭到SYN洪水攻擊,
- tcp傳輸資料時,最新的資料永遠是無法保證可靠性的(最新的資料不會進行確認),當進行三次握手時,只要前兩次失敗客戶端和服務器端就會認為連接沒有建立成功,但是,如果第3三次握手失敗,此時客戶端認為建立成功了而服務器端認為沒有建立成功,不會為其創建相應的資料結構,并且服務器端沒有收到客戶端的ACK確認就會進行超時重傳,當重傳次數達到一定程度后就直接強制斷開連接,因此也不會對客戶端造成很大的影響,但是,如果是四次連接就會導致服務器端認為連接建立成功,而客戶端認為沒有建立成功,此時浪費的是服務器資源,服務器是1對多的,如果大量的客戶端對服務器連接都出現這種問題,就會給服務器帶來巨大的資源浪費,甚至導致服務器崩潰,當然,五次握手和三次握手結果是相同的,但是三次握手是最小保證可靠連接的次數,相比于5/7...節省時間,
- 總結:為什么三次握手可以,第一個原因就是讓吳福氣不要出現建立誤判情況,浪費服務器資源;其次還有一個重要原因就是,以最小成本驗證全雙工(tcp是全雙工的,三次握手就可以保證全雙工通信信道的場通),
四次揮手程序
1)為什么是四次揮手
斷開連接是需要上方同時建立起斷開連接狀態的,因此需要互相請求和確認,一共就是四次揮手,
2)四次揮手的程序
- 客戶端向服務器端發送FIN斷開連接請求,發送成功后客戶端置為FIN_WAIT1狀態,
- 服務器端收到客戶端的FIN請求后,需要向客戶端發送一個ACK確認,發送成功后,服務器端置為CLOS_WAIT狀態,
- 客戶端收到服務器端的ACK確認后進入FIN_WAIT2狀態,
- 服務器端給客戶端發送FIN斷開連接請求,并進入ALST_ACK狀態,
- 客戶端向服務器端發送ACK確認,進入TIME_WAIT狀態,此時客戶端并沒有立刻斷開連接,
- 服務器端收到客戶端的ACK確認后關閉連接,此時服務器端進入CLOSED狀態,斷開連接成功,
理解TIME_WAIT和CLOSE_WAIT狀態
1)TIME_WAIT狀態
為什么客戶端給服務器端發完ACK確認后,沒有立刻進入CLOSED狀態?
對于客戶端的最后一次ACK確認,服務器端不會在進行確認,如果客戶端立刻進入CLOSED狀態,有可能導致服務器端并沒有接收到ACK確認,對FIN進行超時重傳,但是此時客戶端已經斷開連接,服務器端是一直收不到客戶端確認的,只能等到重傳次數到達一定程度強制斷開連接,因此,在客戶端發送完確認后會等待一段時間,如果在改時間內沒有收到服務器端重傳的FIN資料就會斷開連接,否則對重傳的FIN重新進行確認,確保服務器端收到并斷開連接,
其次,客戶端發送完ACK確認進入TIME_WAIT狀態,還有一個重要作用就是防止網路中沒有傳完,保證歷史資料在網路中消散,
2)如何驗證TIME_WAIT狀態?
set|socktop介面,即使?埠處于監聽狀態也可以進行系結,
3)CLOSED_WAIT狀態
首先屏蔽服務器daunt程式中關閉檔案描述符的代碼,啟動服務器,讓客戶端進行鏈接,客戶端連接成功后關掉客戶端,此時客戶端就想服務器端發送了斷開連接的請求,但是由于服務器端屏蔽了close,無法斷開連接,此時,查看服務器狀態就為CLOSE_WAIT狀態,
6、滑動視窗
前面討論的確認應答策略是基于“一次發送,一次確認”,經過“一次發送,一次確認”完成后才能進行下一次發送,這樣資料的傳輸效率會很低,

但是,確認應答機制很好的保證了數傳輸的安全性,為了解決其傳輸效率問題,又引入滑動視窗,華東視窗是指,可以一次性發送一批資料,這一批資料發送的程序不需要等待其中某一個資料的確認,視窗大小就是指這批資料的最大值,
如下圖:
- 發送前四個段時,不需要等待任何ACK,直接將四個段發送完,
- 收到第一個ACK后,滑動視窗向后移動繼續發送接下來的四個段,以此類推


- 在上面這個圖中,整個區域表示的是發送緩沖區,白色區域是滑動視窗
- 滑動視窗中的資料是已經發送等待確認的資料,
- 滑動視窗之前的資料是已經發送并且已經收到確認的資料,
- 滑動視窗之后部分的資料是還沒有發送的資料
- 當接收到一個ACK時,滑動視窗的左邊會右移,
- 當接識訓沖區(16位視窗大小)變大時,滑動視窗右邊右移,因此,當滑動視窗越大時,表示對方的接收能變強,
- 滑動視窗大小除了受對方接識訓沖區剩余大小的影響,還跟擁塞控制有關(后邊詳細講解),因此,滑動視窗越大還表明網路狀況好,網吞吐率高,
新的技術的引入,必然會帶來一些新的問題和挑戰,滑動視窗雖然解決了資料傳輸效率低問題,那么如果資料丟包又該如何重傳呢?
- 接收端收到了資料,但是接收端發送的ACK丟了,

其實,滑動視窗機制已經很好的解決了這個問題,滑動視窗中是可以容忍部分ACK丟包的,只要后續ACK進行確認即可(ACK確認序號表示的是該序號之前的所有資料都已經收到,接下來向收到的資料的序號),例如,上圖中1001的ACK丟了并不影響,只要后邊任意一個到達都表示1~1000的收據已經收到,
- 資料報丟了,接收端,沒有收到,

當資料包真正丟失了,是需要進行重傳的,這也就要求滑動視窗中發送的ACK要確保他之前的資料都已經接收到,例如,接收端接收到的資料的順序是1~1000、5001~6000、4001~5000,當接收到5001~6000的資料后不能立即發送6001的ACK,必須等到6001之前的資料全部到達才能發送,
其次,滑動視窗的重傳機制和之前的超時重傳機制也有所不同,滑動視窗中,如果某一個資料真的丟了(超過時間沒有收到),接收方會給發送方發送的每一個不是丟失的資料發送的確認號都是丟失資料的確認號,當接收端接收到三次這個ACK時,會重新對這個ACK的資料進行重新發送,這種機制叫做高速重發機制,也稱快重傳,
例如:
-
當某一段報文段丟失之后 , 發送端會一直收到 1001 這樣的 ACK, 就像是在提醒發送端 " 我想要的是 1001" 一樣
-
如果發送端主機連續三次收到了同樣一個 "1001" 這樣的應答 , 就會將對應的資料 1001 - 2000 重新發送
-
這個時候接收端收到了 1001 之后 , 再次回傳的 ACK 就是 7001 了 ( 因為 2001 - 7000) 接收端其實之前就已 經收到了, 被放到了接收端作業系統內核的接識訓沖區,
思考1:有了快重傳,為什么還需要超時重傳
其實,超時重傳是一種兜底策略,試想,如果所發送的資料小于3次時,即使資料丟失也引發不了塊重傳,此時還是需要超時重傳進行解決,同時,如果是最后一個資料丟了,也是無法引發快重傳的,
7、流量控制
- 接收端將自己可以接收的緩沖區大小放入 TCP 首部中的 "視窗大小" 欄位, 通過ACK端通知發送端;
- 視窗大小欄位越大, 說明網路的吞吐量越高;
- 接收端一旦發現自己的緩沖區快滿了, 就會將視窗大小設定成一個更小的值通知給發送端;
- 發送端接受到這個視窗之后, 就會減慢自己的發送速度;
- 如果接收端緩沖區滿了, 就會將視窗置為0; 這時發送方不再發送資料, 但是需要定期發送一個視窗探測數
- 據段, 使接收端把視窗大小告訴發送端.

注意:實際上接收端和發送端第一次“協商”視窗大小是在三次我說的額程序中,三次握手建立連接時,SYN包中就包含了視窗大小,
8、擁塞控制

為了解決這個問題,引入了擁塞視窗的概念,開始發送資料的時候,擁塞視窗定義為1,每收到一個ACK擁塞視窗+1,每次發送資料的時候將擁塞視窗和主機端反饋的視窗大小做比較,取最小的作為實際發送的視窗大小,
但是,這樣的擁塞視窗增長速度是指數級別的,,慢啟動只是啟動時速度慢,但是增長速度非常快,為了不增長的那么快, 因此不能使擁塞視窗單純的加倍. 此處引入一個叫做慢啟動的閾值,當擁塞視窗超過這個閾值的時候, 不再按照指數方式增長, 而是按照線性方式增長,

- 當TCP開始啟動的時候, 慢啟動閾值等于視窗最大值;
- 在每次超時重發的時候, 慢啟動閾值會變成原來的一半, 同時擁塞視窗置回1;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286296.html
標籤:其他
上一篇:計算機網路實驗(思科模擬器Cisco Packet Tracer)——路由器配置
下一篇:C語言中的這個小細節你知道嗎?
