目錄
1. TCP數據包結構
2. TCP三次握手 和 四次握手
3. TCP如何保證傳輸可靠性 詳解
4. TCP短連接 與 長連接
5. TCP 粘包和拆包
6. TCP和UDP協議的區別
7. TCP/IP 模型
傳輸層控制協議(Transport Control Protocol),TCP/IP協議棧的核心之一。位於傳輸層,提供面向連接的、可靠的字節流服務。
(一)TCP數據包結構
-
源端口號(16 位):它(連同源主機 IP 地址)標識源主機的一個應用進程。
-
目的端口號( 16 位):它(連同目的主機 IP 地址)標識目的主機的一個應用進程。
TCP的包是沒有IP地址的,那是IP層上的事。但是有源端口和目標端口。
一個TCP連接需要四個元組來表示是同一個連接(src_ip, src_port, dst_ip, dst_port)準確說是五元組,還有一個是協議。但因爲這裏只是說TCP協議,所以,這裏只說四元組。由這無元組可以唯一確定一個 TCP 連接。
-
序列號( 32 位):用來標識從 TCP 源端向 TCP 目的端發送的數據字節流,它存儲當前數據包數據第一個字節的序號。**用來解決網絡包亂序(reordering)問題。**如果將字節流看作在兩個應用程序間的單向流動,則 TCP 用順序號對每個字節進行計數。序號是 32bit 的無符號數,序號到達 2^32 - 1 後又從 0 開始。當建立一個新的連接時, SYN 標誌變 1 ,順序號字段包含由這個主機選擇的該連接的初始順序號 ISN ( Initial Sequence Number )。
-
確認號( 32 位):包含發送確認的一端所期望收到的下一個順序號。因此,確認序號應當是上次已成功收到數據字節順序號加 1 。只有 ACK 標誌爲 1 時確認序號字段纔有效。用來解決不丟包的問題。 TCP 爲應用層提供全雙工服務,這意味數據能在兩個方向上獨立地進行傳輸。因此,連接的每一端必須保持每個方向上的傳輸數據順序號。
-
TCP 報頭長度( 4 位):給出報頭中 32bit 字的數目,它實際上指明數據從哪裏開始。需要這個值是因爲任選字段的長度是可變的。這個字段佔 4bit ,因此 TCP 最多有 60 字節的首部。然而,沒有任選字段,正常的長度是 20 字節。
-
保留位( 6 位):保留給將來使用,目前必須置爲 0 。
-
控制位( control flags , 6 位):在 TCP 報頭中有 6 個標誌比特,它們中的多個可同時被設置爲 1 。依次爲:
- URG :(urgent 緊急位 0/1) 爲 1 表示緊急指針有效,爲 0 則忽略緊急指針值。
- ACK :(acknowledge 確認位 0/1)爲 1 表示確認號有效,爲 0 表示報文中不包含確認信息,忽略確認號字段。
- PSH :(push 推標誌)爲 1 表示是帶有 PUSH 標誌的數據,指示接收方應該儘快將這個報文段交給應用層而不用等待緩衝區裝滿。
- RST :(reset 重置位 0/1)用於復位由於主機崩潰或其他原因而出現錯誤的連接。它還可以用於拒絕非法的報文段和拒絕連接請求。一般情況下,如果收到一個 RST 爲 1 的報文,那麼一定發生了某些問題。
- SYN :(synchronize sequence 序列位 0/1)同步序號,爲 1 表示連接請求,用於建立連接和使順序號同步( synchronize )。
- FIN :(finish 完結位 0/1)用於釋放連接,爲 1 表示發送方已經沒有數據發送了,即關閉本方數據流。
-
窗口大小( 16 位):數據字節數,表示從確認號開始,本報文的源方可以接收的字節數,即源方接收窗口大小。窗口大小是一個 16bit 字段,因而窗口大小最大爲 65535字節。也就是著名的滑動窗口(Sliding Window),用於解決流控的。
-
校驗和( 16 位):此校驗和是對整個的 TCP 報文段,包括 TCP 頭部和 TCP 數據,以 16 位字進行計算所得。這是一個強制性的字段,一定是由發送端計算和存儲,並由接收端進行驗證。
-
緊急指針( 16 位):只有當 URG 標誌置 1 時緊急指針纔有效。緊急指針是一個正的偏移量,和順序號字段中的值相加表示緊急數據最後一個字節的序號。 TCP 的緊急方式是發送端向另一端發送緊急數據的一種方式。
-
選項:最常見的可選字段是最長報文大小,又稱爲 MSS(Maximum Segment Size) 。每個連接方通常都在通信的第一個報文段(爲建立連接而設置 SYN 標誌的那個段)中指明這個選項,它指明本端所能接收的最大長度的報文段。選項長度不一定是 32 位字的整數倍,所以要加填充位,使得報頭長度成爲整字數。
-
數據: TCP 報文段中的數據部分是可選的。在一個連接建立和一個連接終止時,雙方交換的報文段僅有 TCP 首部。如果一方沒有數據要發送,也使用沒有任何數據的首部來確認收到的數據。在處理超時的許多情況中,也會發送不帶任何數據的報文段。
(二)TCP三次握手 和 四次握手
1. TPC三次握手
過程:
最初兩端的TCP進程都處於CLOSED狀態。client是主動打開連接,server是被動打開連接。
- 首先client的TCP客戶進程向server發出連接請求報文段,這時首部中的同步位SYN=1,初始序號seq=x。這時,client的客戶進程就進入SYN-SENT(同步已發送)狀態。
- server收到連接請求報文段後,向client發送確認。在確認報文段中把SYN和ACK位都置爲1,確認號是ack=x+1,初始序號seq=y。這時server的TCP服務器進程就進入SYN-RCVD(同步已收到)狀態。
- client的TCP客戶進程收到server的確認後,還要向server給出確認。確認報文段的ACK置爲1,確認號ack=y+1,序號seq=x+1。這時,TCP連接已經建立,client進入ESTABLISHED(已建立連接)狀態,當server收到client的確認後,也會進入ESTABLISHED狀態。
以上給出的連接建立過程就是常說的TCP三次握手。
爲什麼要三次握手?(爲什麼client還要發送一次確認呢?)
三次握手最主要的目的就是雙方確認自己與對方的發送與接收是正常的。
而第三次握手主要是爲了防止已失效的連接請求報文段突然又傳送到了server,因而產生錯誤。
假定client發出的某一個連接請求報文段在傳輸的過程中並沒有丟失,而是在某個網絡節點長時間滯留了,以致延誤到連接釋放以後的某個時間纔到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤以爲client又發了一次新的連接請求,於是向client發出確認報文段,同意建立連接。假如不採用三次握手,那麼只要server發出確認,新的連接就建立了。由於client並未發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以爲新的運輸連接已經建立了,並一直等待client發來數據,因此白白浪費了許多資源。
採用TCP三次握手的方法可以防止上述現象發生。例如在剛纔的情況下,由於client不會向server的確認發出確認,server由於收不到確認,就知道client並沒有要求建立連接。
爲什麼要傳回syn?
接收端傳回發送端所發送的SYN是:爲了告訴發送端,我接收到的信息確實就是你所發送的信號了。
傳了SYN,爲啥還要傳ACK?
雙方通信無誤必須是兩者互相發送信息都無誤。傳了SYN,證明發送方到接收方的通道沒有問題,但是接收方到發送方的通道還需要ACK信號來進行驗證。
2. 四次握手
過程
數據傳輸結束後,通信的雙方都可釋放連接。
-
現在client和server都處於ESTABLISHED狀態。client的應用進程先向server發出連接釋放報文段,主動關閉TCP連接。client把連接釋放報文段的首部的終止控制位FIN置爲1,序號seq=u,它等於前面已傳送過的數據的最後一個字節的序號加1。這時A進入FIN-WAIT-1(終止等待1)狀態,等待server的確認。
-
server收到連接釋放報文段後即發出確認(發出的不是連接釋放報文段),確認號是ack=u+1,而這個報文段自己的序號是seq = v,等於server前面已傳送過的數據的最後一個字節的序號加1。然後server就進入CLOSE-WAIT(關閉等待)狀態。TCP服務器進程這時通知高層應用進程,因而從client到server這個方向的連接釋放了,這時的TCP連接處於半關閉狀態,即client已經沒有數據要發送了,但server若發送數據,client仍要接受。也就是說,從server到client這個方向的連接並未關閉。這個狀態可以會持續一些時間。
client收到server的確認後,就進入FIN-WAIT-2(終止等待2)狀態,等待server發出的連接釋放報文段。
-
若server已經沒有要向client發送的數據,其應用進程就通知TCP釋放連接。這時server發出的連接釋放報文段必須使用FIN=1。現假定server的序號爲w(在半關閉狀態B可能又發送了一些數據)。server還必須重複上次已發送過的確認號ack=u+1。這是server就進入LAST-ACK狀態,等待A的確認。
-
在client收到server的連接釋放報文段後,必須對此發出確認。在確認報文段中把ACK置爲1,確認號ack=w+1,而自己的序號是seq=u+1(前面的FIN報文消耗了1個序號)。然後進入TIME-WAIT狀態。請注意,現在TCP連接還沒釋放掉。必須再經過2MSL後,client才進入到CLOSED狀態。MSL叫最長報文段壽命,一般爲2分鐘。
當server收到client發出的確認,就進入CLOSED狀態。由此可見server結束TCP連接的時間要比client早一些。等到2MSL結束後client也進入CLOSED狀態,至此完成了TCP四次揮手斷開連接全過程。
tcp四次揮手爲什麼要等待2MSL?(爲什麼要有TIME-WAIT這個狀態呢)
MSL 是Maximum Segment Lifetime,譯爲“報文最大生存時間”,任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。
2MSL是兩倍的MSL(Maximum Segment Lifetime),2MSL就是一個發送和一個回覆所需的最大時間
-
防止客戶端最後一次發給服務器的確認在網絡中丟失以至於客戶端關閉,而服務端並未關閉,導致資源的浪費。
client發送出最後的ACK回覆後,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重複發送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK之後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL,如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。
-
等待最大的2msl可以讓本次連接的所有的網絡包在鏈路上消失,以防造成不必要的干擾。
如果client直接closed,然後又向server發起了一個新連接,我們不能保證這個新連接和剛關閉的連接的端口號是不同的。假設新連接和已經關閉的老端口號是一樣的,如果前一次滯留的某些數據仍然在網絡中,這些延遲數據會在新連接建立後到達Server,所以socket就認爲那個延遲的數據是屬於新連接的,數據包就會發生混淆。所以client要在TIME_WAIT狀態等待2倍的MSL,這樣保證本次連接的所有數據都從網絡中消失。
爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?
因爲在握手過程中,當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。
四次握手因爲是雙方彼此都建立了連接,因此雙方都要釋放自己的連接,A向B發出一個釋放連接請求,他要釋放鏈接表明不再向B發送數據了,此時B收到了A發送的釋放鏈接請求之後,給A發送一個確認,A不能再向B發送數據了,它處於FIN-WAIT-2的狀態,但是此時B還可以向A進行數據的傳送。此時B向A 發送一個斷開連接的請求,A收到之後給B發送一個確認。此時B關閉連接。A也關閉連接。
(三)TCP如何保證傳輸可靠性 詳解
這部分是學習並摘自:TCP如何保證傳輸可靠性
1. 概述
TCP協議保證數據傳輸可靠性的方式主要有:(校序重流擁)
-
校驗和
發送的數據包的二進制相加然後取反,目的是檢測數據在傳輸過程中的任何變化。如果接收端的檢驗和有差錯,TCP將丟棄這個報文段和不確認收到此報文段。
-
確認應答+序列號
TCP給發送的每一個包進行編號,接收方對數據包進行排序,把有序數據傳送給應用層。
-
超時重傳
當TCP發出一個段後,它啓動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發這個報文段。
-
停止等待ARQ協議
也是爲了實現可靠傳輸的,它的基本原理就是每發完一個分組就停止發送,等待對方確認。在收到確認後再發下一個分組。
-
流量控制
TCP連接的每一方都有固定大小的緩衝空間,TCP的接收端只允許發送端發送接收端緩衝區能接納的數據。當接收方來不及處理髮送方的數據,能提示發送方降低發送的速率,防止包丟失。TCP使用的流量控制協議是可變大小的滑動窗口協議。 接收方有即時窗口(滑動窗口),隨ACK報文發送 。
-
擁塞控制
當網絡擁塞時,減少數據的發送。發送方有擁塞窗口,發送數據前比對接收方發過來的即時窗口,取小。
擁塞控制主要是四個算法:慢啓動、擁塞避免、快重傳、快速恢復。
-
應用數據切割:應用數據被分隔成TCP認爲最適合發送的多個報文段(由特定的算法和機制來確認)
接下來詳細說明上面列舉的幾種舉措!
2. 校驗和
計算方式:在數據傳輸的過程中,將發送的數據段都當做一個16位的整數。將這些整數加起來。並且前面的進位不能丟棄,補在後面,最後取反,得到校驗和。
發送方:在發送數據之前計算檢驗和**,**並進行校驗和的填充。
接收方:收到數據後,對數據以同樣的方式進行計算,求出校驗和,與發送方的進行比對。
注意:如果接收方比對校驗和與發送方不一致,那麼數據一定傳輸有誤。但是如果接收方比對校驗和與發送方一致,數據不一定傳輸成功。
3. 確認應答與序列號
序列號:TCP傳輸時將每個字節的數據都進行了編號,這就是序列號。
確認應答:TCP傳輸的過程中,每次接收方收到數據後,都會對傳輸方進行確認應答。也就是發送ACK報文。這個ACK報文當中帶有對應的確認序列號,告訴發送方,接收到了哪些數據,下一次的數據從哪裏發。
序列號的作用不僅僅是應答的作用,有了序列號能夠將接收到的數據根據序列號排序,並且去掉重複序列號的數據。這也是TCP傳輸可靠性的保證之一。
4. 超時重傳
在進行TCP傳輸時,由於確認應答與序列號機制,也就是說發送方發送一部分數據後,都會等待接收方發送的ACK報文,並解析ACK報文,判斷數據是否傳輸成功。
如果發送方發送完數據後,遲遲沒有等到接收方的ACK報文,這該怎麼辦呢?而沒有收到ACK報文的原因可能是什麼呢?
首先,發送方沒有接收到響應的ACK報文原因可能有兩點:
- 數據在傳輸過程中由於網絡原因等直接全體丟包,接收方沒有接收到。
- 接收方接收到了響應的數據,但是發送的ACK報文響應卻由於網絡原因丟包了。
TCP在解決這個問題的時候引入了一個新的機制,叫做**超時重傳機制。**簡單理解就是發送方在發送完數據後等待一個時間,時間到達沒有接收到ACK報文,那麼對剛纔發送的數據進行重新發送。
- 如果是剛纔第一個原因,接收方收到二次重發的數據後,便進行ACK應答。
- 如果是第二個原因,接收方發現接收的數據已存在(判斷存在的根據就是序列號,所以上面說序列號還有去除重複數據的作用),那麼直接丟棄,仍舊發送ACK應答。
那麼發送方發送完畢後**等待的時間是多少呢?**如果這個等待的時間過長,那麼會影響TCP傳輸的整體效率,如果等待時間過短,又會導致頻繁的發送重複的包。如何權衡?
由於TCP傳輸時保證能夠在任何環境下都有一個高性能的通信,因此這個最大超時時間(也就是等待的時間)是動態計算的。
注意:
超時以500ms(0.5秒)爲一個單位進行控制,每次判定超時重發的超時時間都是500ms的整數倍。重發一次後,仍未響應,那麼等待2500ms的時間後,再次重傳。等待4500ms的時間繼續重傳。以一個指數的形式增長。累計到一定的重傳次數,TCP就認爲網絡或者對端出現異常,強制關閉連接。
詳細內容推薦閱讀以下博客!
5. 停止等待協議
- 停止等待協議是爲了實現可靠傳輸的,它的基本原理就是每發完一個分組就停止發送,等待對方確認。在收到確認後再發下一個分組。
- 爲了提高傳輸效率,發送方可以不使用低效率的停止等待協議,而是採用流水線傳輸。流水線傳輸就是發送方可連續發送多個分組,不必每發完一個分組就停下來等待對方確認。這樣可使信道上一直有數據不間斷的在傳送。這種傳輸方式可以明顯提高信道利用率。
6. 流量控制
接收端在接收到數據後,對其進行處理。如果發送端的發送速度太快,導致接收端的結束緩衝區很快的填充滿了。此時如果發送端仍舊發送數據,那麼接下來發送的數據都會丟包,繼而導致丟包的一系列連鎖反應,超時重傳呀什麼的。而TCP根據接收端對數據的處理能力,決定發送端的發送速度,這個機制就是流量控制。流量控制所要做的就是控制發送端發送數據的速率,以便使接收端來得及接受。流量控制往往指的是點對點通信量的控制,是個端到端的問題。
在TCP協議的報頭信息當中,有一個16位字段的窗口大小。在介紹這個窗口大小時我們知道,窗口大小的內容實際上是接收端接收數據緩衝區的剩餘大小。這個數字越大,證明接收端接收緩衝區的剩餘空間越大,網絡的吞吐量越大。接收端會在確認應答發送ACK報文時,將自己的即時窗口大小填入,並跟隨ACK報文一起發送過去。而發送方根據ACK報文裏的窗口大小的值的改變進而改變自己的發送速度。如果接收到窗口大小的值爲0,那麼發送方將停止發送數據。並定期的向接收端發送窗口探測數據段,讓接收端把窗口大小告訴發送端。
注:16位的窗口大小最大能表示65535個字節(64K),但是TCP的窗口大小最大並不是64K。在TCP首部中40個字節的選項中還包含了一個窗口擴大因子M,實際的窗口大小就是16爲窗口字段的值左移M位。每移一位,擴大兩倍。
7. 擁塞控制
TCP傳輸的過程中,發送端開始發送數據的時候,如果剛開始就發送大量的數據,那麼就可能造成一些問題。網絡可能在開始的時候就很擁堵,如果給網絡中在扔出大量數據,那麼這個擁堵就會加劇。擁堵的加劇就會產生大量的丟包,就對大量的超時重傳,嚴重影響傳輸。
擁塞控制就是防止過多的數據注入到網絡中,這樣可以使網絡中的路由器或鏈路不致過載。
擁塞控制是TCP在傳輸時儘可能快的將數據傳輸,並且避免擁塞造成的一系列問題。是可靠性的保證,同時也是維護了傳輸的高效性。
發送方維持一個叫做擁塞窗口 cwnd(congestion window)的狀態變量。擁塞窗口的大小取決於網絡的擁塞程度,並且動態地在變化。發送方讓自己的發送窗口等於擁塞窗口,另外考慮到接受方的接收能力,發送窗口可能小於擁塞窗口。
擁塞控制主要是四個算法:慢開始、擁塞避免、快重傳、快恢復。
-
慢啓動 與 擁塞避免
慢開始算法的思路就是:在開始發送數據時,先發送少量的數據探路。探清當前的網絡狀態如何,再決定多大的速度進行傳輸。
最初的TCP在連接建立成功後會向網絡中發送大量的數據包,這樣很容易導致網絡中路由器緩存空間耗盡,從而發生擁塞。因此新建立的連接不能夠一開始就大量發送數據包,而只能根據網絡情況逐步增加每次發送的數據量,以避免上述現象的發生。具體來說,當新建連接時,cwnd初始化爲1個最大報文段(MSS)大小,發送端開始按照擁塞窗口大小發送數據,每當有一個報文段被確認,cwnd就增加1個MSS大小。這樣cwnd的值就隨着網絡往返時間(Round Trip Time,RTT)呈指數級增長,事實上,慢啓動的速度一點也不慢,只是它的起點比較低一點而已。我們可以簡單計算下:
開始 ---> cwnd = 1 經過1個RTT後 ---> cwnd = 2*1 = 2 經過2個RTT後 ---> cwnd = 2*2= 4 經過3個RTT後 ---> cwnd = 4*2 = 8 如果帶寬爲W,那麼經過RTT*log2W時間就可以佔滿帶寬。
從慢啓動可以看到,cwnd可以很快的增長上來,從而最大程度利用網絡帶寬資源,但是cwnd不能一直這樣無限增長下去,一定需要某個限制。TCP使用了一個叫慢啓動門限(ssthresh)的變量,當cwnd超過該值後,慢啓動過程結束,進入擁塞避免階段。對於大多數TCP實現來說,ssthresh的值是65536(同樣以字節計算)。擁塞避免的主要思想是加法增大,也就是cwnd的值不再指數級往上升,開始加法增加。此時當窗口中所有的報文段都被確認時,cwnd的大小加1,cwnd的值就隨着RTT開始線性增加,這樣就可以避免增長過快導致網絡擁塞,慢慢的增加調整到網絡的最佳值。
當cwnd<ssthresh時,使用慢開始算法。
當cwnd>ssthresh時,改用擁塞避免算法。
當cwnd=ssthresh時,慢開始與擁塞避免算法任意。
無論是在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有收到確認,雖然沒有收到確認可能是其他原因的分組丟失,但是因爲無法判定,所以都當做擁塞來處理),就將cwnd置爲1,ssthresh置爲cwnd的一半,然後開始執行慢啓動算法(cwnd<ssthresh)。
-
快重傳 和 快恢復
在TCP/IP中,快速重傳和恢復 FRR(fast retransmit and recovery)是一種擁塞控制算法,它能快速恢復丟失的數據包。沒有FRR,如果數據包丟失了,TCP將會使用定時器來要求傳輸暫停。在暫停的這段時間內,沒有新的或複製的數據包被髮送。有了FRR,如果接收機接收到一個不按順序的數據段,它會立即給發送機發送一個重複確認。如果發送機接收到三個重複確認,它會假定確認件指出的數據段丟失了,並立即重傳這些丟失的數據段。有了FRR,就不會因爲重傳時要求的暫停被耽誤。 當有單獨的數據包丟失時,快速重傳和恢復(FRR)能最有效地工作。當有多個數據信息包在某一段很短的時間內丟失時,它則不能很有效地工作。
詳細內容推薦閱讀以下博客!
8. 連接管理
連接管理就是三次握手與四次揮手的過程,在前面詳細講過這個過程,這裏不再贅述。保證可靠的連接,是保證可靠性的前提。
(四)TCP短連接 與 長連接
學習並整理摘於 :TCP長連接與短連接
當網絡通信時採用TCP協議時,在真正的讀寫操作之前,server與client之間必須建立一個連接,當讀寫操作完成後,雙方不再需要這個連接時它們可以釋放這個連接,連接的建立是需要三次握手的,而釋放則需要4次握手,所以說每個連接的建立都是需要資源消耗和時間消耗的。
1. 短連接
模擬一下TCP短連接的情況:
- client 向 server 發起連接請求
- server 接到請求,雙方建立連接
- client 向 server 發送消息
- server 迴應 client
- 一次讀寫完成,此時雙方任何一個都可以發起 close 操作
在第 5 點中,一般都是 client 先發起 close 操作。因爲一般的 server 不會回覆完 client 後就立即關閉連接。當然也不排除有特殊的情況。
短連接一般只會在 client/server 間傳遞一次讀寫操作!
短連接的操作步驟是:
- 建立連接——數據傳輸——關閉連接…建立連接——數據傳輸——關閉連接
短連接的優缺點是:
- 優點:管理起來比較簡單,存在的連接都是有用的連接,不需要額外的控制手段。
- 缺點是:但如果客戶請求頻繁,將在TCP的建立和關閉操作上浪費時間和帶寬。
短連接應用場景:
像WEB網站的http服務一般都用短鏈接,因爲長連接對於服務端來說會耗費一定的資源,而像WEB網站這麼頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都佔用一個連接的話,那可想而知吧。所以併發量大,但每個用戶無需頻繁操作情況下需用短連好。
2. 長連接
模擬一下長連接的情況:
- client 向 server 發起連接
- server 接到請求,雙方建立連接
- client 向 server 發送消息
- server 迴應 client
- 一次讀寫完成,連接不關閉
- 後續讀寫操作…
長連接的操作步驟是:
- 建立連接——數據傳輸…(保持連接)…數據傳輸——關閉連接
而長連接的狀態是如何保持的呢?有些博主已經總結的很好,這裏就不加篇(ctrl)幅(c+v _)。推薦看下面博客:
長連接的優缺點是:
- 優點:長連接可以省去較多的TCP建立和關閉的操作,減少浪費,節約時間。
- 缺點:在長連接的應用場景下,client端一般不會主動關閉它們之間的連接,client與server之間的連接如果一直不關閉的話,會存在一個問題,隨着客戶端連接越來越多,server早晚有扛不住的時候,這時候server端需要採取一些策略,如關閉一些長時間沒有讀寫事件發生的連接,這樣可以避免一些惡意連接導致server端服務受損;如果條件再允許就可以以客戶端機器爲顆粒度,限制每個客戶端的最大長連接數。
長連接應用場景:
長連接多用於操作頻繁,點對點的通訊,而且連接數不能太多情況。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話那麼處理速度會降低很多,所以每個操作完後都不斷開,再次處理時直接發送數據包就OK了,不用建立TCP連接。例如:數據庫的連接用長連接,如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。
(五)TCP 粘包和拆包
學習並摘自:tcp粘包和拆包
粘包拆包問題是處於網絡比較底層的問題,在數據鏈路層、網絡層以及傳輸層都有可能發生。我們日常的網絡應用開發大都在傳輸層進行,由於UDP有消息保護邊界,不會發生粘包拆包問題,因此粘包拆包問題只發生在TCP協議中。
1. 什麼是粘包、拆包?
假設客戶端向服務端連續發送了兩個數據包,用packet1和packet2來表示,那麼服務端收到的數據可以分爲三種,現列舉如下:
第一種情況,接收端正常收到兩個數據包,即沒有發生拆包和粘包的現象,此種情況不在本文的討論範圍內。
第二種情況,接收端只收到一個數據包,由於TCP是不會出現丟包的,所以這一個數據包中包含了發送端發送的兩個數據包的信息,這種現象即爲粘包。這種情況由於接收端不知道這兩個數據包的界限,所以對於接收端來說很難處理。
第三種情況,這種情況有兩種表現形式,如下圖。接收端收到了兩個數據包,但是這兩個數據包要麼是不完整的,要麼就是多出來一塊,這種情況即發生了拆包和粘包。這兩種情況如果不加特殊處理,對於接收端同樣是不好處理的。
2. 爲什麼會發生TCP粘包、拆包?
發生TCP粘包、拆包主要是由於下面一些原因:
- 應用程序寫入的數據大於套接字緩衝區大小,這將會發生拆包。
- 應用程序寫入數據小於套接字緩衝區大小,網卡將應用多次寫入的數據發送到網絡上,這將會發生粘包。
- 進行MSS(最大報文長度)大小的TCP分段,當TCP報文長度-TCP頭部長度>MSS的時候將發生拆包。
- 接收方法不及時讀取套接字緩衝區數據,這將發生粘包。
3. 粘包、拆包解決辦法
TCP本身是面向流的,作爲網絡服務器,如何從這源源不斷涌來的數據流中拆分出或者合併出有意義的信息呢?通常會有以下一些常用的方法:
- 發送端給每個數據包添加包首部,首部中應該至少包含數據包的長度,這樣接收端在接收到數據後,通過讀取包首部的長度字段,便知道每一個數據包的實際長度了。
- 發送端將每個數據包封裝爲固定長度(不夠的可以通過補0填充),這樣接收端每次從接收緩衝區中讀取固定長度的數據就自然而然的把每個數據包拆分開來。
- 可以在數據包之間設置邊界,如添加特殊符號,這樣,接收端通過這個邊界就可以將不同的數據包拆分開。
(六)TCP和UDP協議的區別
1. UDP數據包結構
用戶數據報協議(User Datagram Protocol, UDP),是一種無連接方式的、不可靠的傳輸協議。
- 源端口號和目的端口號如上和TCP的相同。
- UDP長度:UDP報文的字節長度(包括首部和數據)。
- UDP校驗和: 檢驗UDP首部和數據部分的正確性。
2. TCP與UDP區別
特點 | TCP | UDP |
---|---|---|
連接性 | 面向連接 | 面向非連接 |
可靠性 | 可靠 | 不可靠 |
報文 | 面向字節流 | 面向報文 |
傳輸效率 | 低 | 高 |
傳輸速度 | 慢 | 快 |
雙工性 | 全雙工 | 一對一、一對多、多對一、多對多 |
流量控制 | 滑動窗口 | 無 |
擁塞控制 | 慢開始、擁塞控制、快重傳、快恢復 | 無 |
應用場景 | 對效率要求低、對準確性要求高或者要求有連接的場景 | 對效率要求高、對準確性要求低的場景 |
TCP和UDP協議的一些應用:
應用層協議 | 應用 | 傳輸層協議 |
---|---|---|
SMTP | 電子郵件 | TCP |
TELNET | 遠程終端接入 | TCP |
HTTP | 萬維網 | TCP |
FIP | 文件傳輸 | TCP |
DNS | 域名轉換 | UDP |
TFIP | 文件傳輸 | UDP |
SNMP | 網絡管理 | UDP |
NFS | 遠程文件服務器 | UDP |
(七) TCP/IP 模型
TCP/IP協議模型(Transmission Control Protocol/Internet Protocol),包含了一系列構成互聯網基礎的網絡協議,是Internet的核心協議。
基於TCP/IP的參考模型將協議分成四個層次,它們分別是鏈路層(網絡接口層)、網絡層、傳輸層和應用層。下圖表示TCP/IP模型與OSI模型各層的對照關係。
其中各層作用:
- 應用層:決定了向用戶提供應用服務時通信的活動,主要負責應用之間的數據傳輸。
- 傳輸層:主要負責的功能是將應用層的數據進行傳輸,爲爲兩臺主機上的應用提供端到端的通信。
- 網絡層:主要處理在網絡中傳輸的數據包,定義了數據包在網絡中傳輸的格式。
- 鏈路層:處理連接網絡的硬件部分,是這些硬件部分之間通信規範的一個標準,使這些硬件設備之間能夠相互連接。
TCP/IP協議通信的過程其實就對應着數據入棧與出棧的過程。入棧的過程,數據發送方每層不斷地封裝首部與尾部,添加一些傳輸的信息,確保能傳輸到目的地。出棧的過程,數據接收方每層不斷地拆除首部與尾部,得到最終傳輸的數據。