IP協(xié)議是無(wú)連接的通訊協(xié)議不會(huì)占用兩個(gè)正在通訊的計(jì)算機(jī)之間的通訊線路,這樣IP就降低了對(duì)網(wǎng)絡(luò)線路的需求,每條線可以同時(shí)滿足許多不同計(jì)算機(jī)之間的通訊需要.
通過(guò)IP,消息或者其他數(shù)據(jù)會(huì)被分割為較小的獨(dú)立的包并通過(guò)因特網(wǎng)在計(jì)算機(jī)之間傳送
IP負(fù)責(zé)將每個(gè)包路由到目的地,但是IP協(xié)議沒用做任何工作去確認(rèn)數(shù)據(jù)是否按順序發(fā)送或者包是否被破壞,所以IP數(shù)據(jù)包是不可靠的,因此需要它的上層傳輸層TCP協(xié)議來(lái)做控制!
TCP(Transmission Control Protocol 傳輸控制協(xié)議)
- 面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議
- 將應(yīng)用層的數(shù)據(jù)流分割成報(bào)文段(報(bào)文段長(zhǎng)度受MTU影響)并發(fā)送給目標(biāo)節(jié)點(diǎn)的TCP層
-
數(shù)據(jù)包都有序號(hào),對(duì)方收到則發(fā)送ACK(確認(rèn)字符)確認(rèn),未收到則重傳 - 使用校驗(yàn)和來(lái)檢驗(yàn)數(shù)據(jù)在傳輸過(guò)程中是否有誤
報(bào)文頭介紹

源端口標(biāo)識(shí)發(fā)起通信的那個(gè)進(jìn)程,目的端口標(biāo)識(shí)接受通信的那個(gè)進(jìn)程。
有了端口號(hào),接受到報(bào)文后才能夠知道將報(bào)文發(fā)送到哪個(gè)進(jìn)程。
在TCP傳輸中,每一個(gè)字節(jié)都是有序號(hào)的,從0開始。通過(guò)序號(hào)的方式保存數(shù)據(jù)的順序,接收端接受到之后進(jìn)行
重新排列成為需要的數(shù)據(jù)。
因此,我對(duì)于SEQ和ACK的了解就是:
seq(Sequence Nubmer) 代表:發(fā)送的這個(gè)包中第一個(gè)字節(jié)(如果有payload的話)的序號(hào)
ack(Acknowledgement) 代表:已成功接受序列號(hào)到 ack-1 的數(shù)據(jù),期望接收的下一個(gè)字節(jié)的序號(hào)為 ack
首部長(zhǎng)度(Data Offset):表示TCP報(bào)文首部信息的長(zhǎng)度。由于首部可能含有選項(xiàng)內(nèi)容,因?yàn)門CP首部的長(zhǎng)度是不確定的。首部長(zhǎng)度指示了數(shù)據(jù)區(qū)在報(bào)文段中的起始偏移值。沒有任何選項(xiàng)字段的TCP頭部長(zhǎng)度為20字節(jié),做多可以有60字節(jié)的TCP頭部。
保留(Reserved):6位保留字段,值通常為0;
TCP Flags標(biāo)志位(每個(gè)標(biāo)志位表示一個(gè)控制功能)
◆URG:緊急指針(為0無(wú)效忽略,為1有效)
◆ACK:確認(rèn)序號(hào)(為0表示報(bào)文中不含確認(rèn)信息忽略確認(rèn)號(hào)字段,為1表示確認(rèn)號(hào)有效)
◆PSH:(為1表示帶有PAH數(shù)據(jù)讓接收方應(yīng)該盡快將這個(gè)報(bào)文段交給應(yīng)用層,不在緩沖區(qū)排隊(duì))
◆RST:重建連接。(用于重置由于主機(jī)崩潰或其他原因出現(xiàn)錯(cuò)誤的鏈接或用于拒絕非法報(bào)文段和非法請(qǐng)求)
◆SYN:同步序列號(hào),用于建立連接過(guò)程
◆FIN:finsh標(biāo)志,用于釋放連接。為1時(shí)表示發(fā)送方已經(jīng)沒有數(shù)據(jù)發(fā)送了
- window指滑動(dòng)窗口大小,用來(lái)告知發(fā)送端目的接收端的緩存大小以此來(lái)控制發(fā)送端發(fā)送數(shù)據(jù)的速率以此達(dá)到流量控制的效果
- CheckSum 校驗(yàn)和:奇偶校驗(yàn)。對(duì)整個(gè)TCP報(bào)文段,即TCP頭部和TCP數(shù)據(jù)進(jìn)行校驗(yàn)和計(jì)算以16位進(jìn)行計(jì)算所得,由發(fā)送端計(jì)算和存儲(chǔ),并由接收端進(jìn)行驗(yàn)證
- 緊急指針(Urgent Pointer):只有TCPFlags中URG=1時(shí)有效,如果TCP通信中,一方有緊急的數(shù)據(jù)需要盡快發(fā)送給接收方,并且讓接收方的TCP協(xié)議盡快通知相應(yīng)的應(yīng)用程序,可以將URG置位,并通過(guò)緊急指針指示緊急數(shù)據(jù)在報(bào)文段中的結(jié)束位置。占16比特。它是一個(gè)偏移量,和序號(hào)字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號(hào)。
- Options可定義一些其他參數(shù)
TCP的三次握手流程

這里每次傳遞seq ack+1的原因是每次一個(gè)報(bào)文傳送告知,都要消耗一個(gè)序號(hào)
書面解釋,專業(yè)回答
```
在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接。
第一次握手:建立連接時(shí),客戶端發(fā)送SYN包(syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到SYN包,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包(syn=k)
即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢
客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手。
三次握手模擬,只限理解,專業(yè)回答看上面
兩者建立鏈接的過(guò)程類似于彼此確認(rèn)彼此能否正確的收到信息
(類似于相互在進(jìn)行一次小型的通訊)
```
AB在一個(gè)很高的樓層想嘗試帶彼此東西上樓,于是要嘗試能不能收到彼此的東西,
:第一次握手,SYN=1,A告訴B,老子要給你送東西了,seq=X,你在x樓等包裹
:第二次握手,ACK=1,老子聽到了你說(shuō)啥了,SYN=1,B告訴A,老子愿意收,我這就去x樓等你,ack=x+1,我在在x樓了,下一次x+1樓,seq=y,我把你的重新給你我再給你我自己的東西你試試能不能收到,你到y(tǒng)樓等我)
:第三次握手,ACK=1,我收到我發(fā)的包和你發(fā)的包了,沒問題,seq=x+1,你下次去的樓是x+1樓,sck=y+1,老子到y(tǒng)樓了,下一層y+1樓;
```
哈哈哈除了我大概別人也難看懂
為什么需要三次握手才能建立鏈接???
為了初始化Sequence Number的初始值,其實(shí)就是上面的x和y,通訊雙方要告訴彼此自己的Sequence Number這個(gè)號(hào)要作為以后數(shù)據(jù)通訊的序號(hào),以保證應(yīng)用層接收到的數(shù)據(jù)接收到的數(shù)據(jù)不會(huì)因?yàn)榫W(wǎng)絡(luò)上的問題而產(chǎn)生問題,即TCP會(huì)用這個(gè)序號(hào)來(lái)拼接數(shù)據(jù),因此服務(wù)器端收到客戶端的Sequence Number要發(fā)送一個(gè)確認(rèn)報(bào)文,告訴客戶端,我已收到你的Sequence Number;
首次握手的隱患-SYN超時(shí),可能導(dǎo)致SYN Flood
問題原因:
- Server收到Client的SYN,回復(fù)SYN-ACK的時(shí)候未收到ACK確認(rèn)(比如IP地址是偽造的,服務(wù)器找不到)
- Server不斷重試直至超時(shí),Linux默認(rèn)等待63秒才斷開連接(重試5次,間隔時(shí)間翻倍1,2,4,8,16,32)
后果
可能服務(wù)器收到SYN Flood的風(fēng)險(xiǎn),每一次這樣的鏈接會(huì)讓服務(wù)器等待63秒,如果有很多這樣的請(qǐng)求,導(dǎo)致服務(wù)器打開了大量的SYNC_RECV半連接,就會(huì)把TCP的連接隊(duì)列耗盡,最后導(dǎo)致TCP無(wú)法對(duì)其他TCP連接進(jìn)行響應(yīng)。
針對(duì)SYN Flood的預(yù)防措施
- SYN隊(duì)列滿后,TCP通過(guò)源地址端口目標(biāo)地址端口和時(shí)間戳打造出一個(gè)
tcp_syncookies(可看作Sequence Numbe)參數(shù)回發(fā)SYN Cookie - 若為正常連接則Client會(huì)回發(fā)
SYN Cookie,直接建立連接(即使服務(wù)器隊(duì)列滿了也可以)
參考1,SYN Flood詳解
參考2,SYN FLOOD前的嗅探
若建立連接后Client出現(xiàn)故障怎么辦?
TCP設(shè)有?;顧C(jī)制
- 若一段時(shí)間內(nèi)(?;顣r(shí)間)若連接處于非活動(dòng)狀態(tài),開啟?;罟δ艿囊欢蜗?qū)Ψ桨l(fā)送
保活探測(cè)報(bào)文,如果未收到響應(yīng)則繼續(xù)發(fā)送 - 嘗試次數(shù)達(dá)到?;钐綔y(cè)數(shù)仍未收到響應(yīng)(這時(shí)可以確認(rèn)對(duì)方主機(jī)為不可達(dá))則中斷連接
TCP粘包問題解決
TCP粘包是指:發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時(shí)粘成一包
發(fā)送方原因:
TCP默認(rèn)使用Nagle算法(主要作用:減少網(wǎng)絡(luò)中報(bào)文段的數(shù)量):
收集多個(gè)小分組,在一個(gè)確認(rèn)到來(lái)時(shí)一起發(fā)送、導(dǎo)致發(fā)送方可能會(huì)出現(xiàn)粘包問題
接收方原因:
TCP將接收到的數(shù)據(jù)包保存在接收緩存里,如果TCP接收數(shù)據(jù)包到緩存的速度大于應(yīng)用程序從緩存中讀取數(shù)據(jù)包的速度,多個(gè)包就會(huì)被緩存,應(yīng)用程序就有可能讀取到多個(gè)首尾相接粘到一起的包。
解決粘包問題:
- 最本質(zhì)原因在與接收對(duì)等方無(wú)法分辨消息與消息之間的邊界在哪,通過(guò)使用某種方案給出邊界,例如:
- 發(fā)送定長(zhǎng)包。每個(gè)消息的大小都是一樣的,接收方只要累計(jì)接收數(shù)據(jù),直到數(shù)據(jù)等于一個(gè)定長(zhǎng)的數(shù)值就將它作為一個(gè)消息。
- 包尾加上\r\n標(biāo)記。FTP協(xié)議正是這么做的。但問題在于如果數(shù)據(jù)正文中也含有\(zhòng)r\n,則會(huì)誤判為消息的邊界。
- 包頭加上包體長(zhǎng)度。包頭是定長(zhǎng)的4個(gè)字節(jié),說(shuō)明了包體的長(zhǎng)度。接收對(duì)等方先接收包體長(zhǎng)度,依據(jù)包體長(zhǎng)度來(lái)接收包體。