日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

计算机网络是如何通信的【二】

發布時間:2024/10/5 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机网络是如何通信的【二】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TCP三次握手和四次揮手以及11種狀態

?

1、三次握手

置位概念:根據TCP的包頭字段,存在3個重要的標識ACK、SYN、FIN?
ACK:表示驗證字段?
SYN:位數置1,表示建立TCP連接?
FIN:位數置1,表示斷開TCP連接

三次握手過程說明:?
1、由客戶端發送建立TCP連接的請求報文,其中報文中包含seq序列號,是由發送端隨機生成的,并且將報文中的SYN字段置為1,表示需要建立TCP連接。(SYN=1,seq=x,x為隨機生成數值)
2、由服務端回復客戶端發送的TCP連接請求報文,其中包含seq序列號,是由回復端隨機生成的,并且將SYN置為1,而且會產生ACK字段,ACK字段數值是在客戶端發送過來的序列號seq的基礎上加1進行回復,以便客戶端收到信息時,知曉自己的TCP建立請求已得到驗證。(SYN=1,ACK=x+1,seq=y,y為隨機生成數值)這里的ack加1可以理解為是確認和誰建立連接。
3、客戶端收到服務端發送的TCP建立驗證請求后,會使自己的序列號加1表示,并且再次回復ACK驗證請求,在服務端發過來的seq上加1進行回復。(SYN=1,ACK=y+1,seq=x+1)

2、四次揮手

四次揮手過程說明:?
1、客戶端發送斷開TCP連接請求的報文,其中報文中包含seq序列號,是由發送端隨機生成的,并且還將報文中的FIN字段置為1,表示需要斷開TCP連接。(FIN=1,seq=x,x由客戶端隨機生成)

2、服務端會回復客戶端發送的TCP斷開請求報文,其包含seq序列號,是由回復端隨機生成的,而且會產生ACK字段,ACK字段數值是在客戶端發過來的seq序列號基礎上加1進行回復,以便客戶端收到信息時,知曉自己的TCP斷開請求已經得到驗證。(FIN=1,ACK=x+1,seq=y,y由服務端隨機生成)
3、服務端在回復完客戶端的TCP斷開請求后,不會馬上進行TCP連接的斷開,服務端會先確保斷開前,所有傳輸到A的數據是否已經傳輸完畢,一旦確認傳輸數據完畢,就會將回復報文的FIN字段置1,并且產生隨機seq序列號。(FIN=1,ACK=x+1,seq=z,z由服務端隨機生成)
4、客戶端收到服務端的TCP斷開請求后,會回復服務端的斷開請求,包含隨機生成的seq字段和ACK字段,ACK字段會在服務端的TCP斷開請求的seq基礎上加1,從而完成服務端請求的驗證回復。(FIN=1,ACK=z+1,seq=h,h為客戶端隨機生成)?
至此TCP斷開的4次揮手過程完畢

1、一開始,建立連接之前服務器和客戶端的狀態都為CLOSED;?
2、服務器創建socket后開始監聽,變為LISTEN狀態;?
3、客戶端請求建立連接,向服務器發送SYN報文,客戶端的狀態變味SYN_SENT;?
4、服務器收到客戶端的報文后向客戶端發送ACK和SYN報文,此時服務器的狀態變為SYN_RCVD;?
5、然后,客戶端收到ACK、SYN,就向服務器發送ACK,客戶端狀態變為ESTABLISHED;?
6、服務器端收到客戶端的ACK后變為ESTABLISHED。此時3次握手完成,連接建立!

由于TCP連接是全雙工的,斷開連接會比建立連接麻煩一點點。?
1、客戶端先向服務器發送FIN報文,請求斷開連接,其狀態變為FIN_WAIT1;?
2、服務器收到FIN后向客戶端發送ACK,服務器的狀態圍邊CLOSE_WAIT;?
3、客戶端收到ACK后就進入FIN_WAIT2狀態,此時連接已經斷開了一半了。如果服務器還有數據要發送給客戶端,就會繼續發送;?
4、直到發完數據,就會發送FIN報文,此時服務器進入LAST_ACK狀態;?
5、客戶端收到服務器的FIN后,馬上發送ACK給服務器,此時客戶端進入TIME_WAIT狀態;?
6、再過了2MSL長的時間后進入CLOSED狀態。服務器收到客戶端的ACK就進入CLOSED狀態。?
至此,還有一個狀態沒有出來:CLOSING狀態。?
CLOSING狀態表示:?
客戶端發送了FIN,但是沒有收到服務器的ACK,卻收到了服務器的FIN,這種情況發生在服務器發送的ACK丟包的時候,因為網絡傳輸有時會有意外。

LISTEN:等待從任何遠端TCP 和端口的連接請求。SYN_SENT:發送完一個連接請求后等待一個匹配的連接請求。SYN_RECEIVED:發送連接請求并且接收到匹配的連接請求以后等待連接請求確認。ESTABLISHED:表示一個打開的連接,接收到的數據可以被投遞給用戶。連接的數據傳輸階段的正常狀態。FIN_WAIT_1:等待遠端TCP 的連接終止請求,或者等待之前發送的連接終止請求的確認。FIN_WAIT_2:等待遠端TCP 的連接終止請求。CLOSE_WAIT:等待本地用戶的連接終止請求。CLOSING:等待遠端TCP 的連接終止請求確認。LAST_ACK:等待先前發送給遠端TCP 的連接終止請求的確認(包括它字節的連接終止請求的確認)TIME_WAIT:等待足夠的時間過去以確保遠端TCP 接收到它的連接終止請求的確認。 TIME_WAIT 兩個存在的理由:1.可靠的實現tcp全雙工連接的終止;2.允許老的重復分節在網絡中消逝。CLOSED:不在連接狀態(這是為方便描述假想的狀態,實際不存在)

3、TCP 報文段簡介

TCP 首部包含以下內容,請留意其中的控制位,在三次握手和四次揮手過程中會頻繁出現:

  • 端口號 (Source Port and Destination Port):每個 TCP 報文段都包含源端和目的端的端口號,用于尋找發送端和接收端應用進程。這兩個值加上 IP 首部中的源端 IP 地址和目的端 IP 地址就可以確定一個唯一的 TCP 連接。
  • 序號 (Sequence Number):這個字段的主要作用是用于將失序的數據重新排列。TCP 會隱式地對字節流中的每個字節進行編號,而 TCP 報文段的序號被設置為其數據部分的第一個字節的編號。序號是 32 bit 的無符號數,取值范圍是0到 232 - 1。
  • 確認序號 (Acknowledgment Number):接收方在接受到數據后,會回復確認報文,其中包含確認序號,作用就是告訴發送方自己接收到了哪些數據,下一次數據從哪里開始發,因此,確認序號應當是上次已成功收到數據字節序號加 1。只有 ACK 標志為 1 時確認序號字段才有效。
  • 首部長度 (Header Length):首部中的選項部分的長度是可變的,因此首部的長度也是可變的,所以需要這個字段來明確表示首部的長度,這個字段占 4 bit,4 位的二進制數最大可以表示 15,而首部長度是以 4 個字節為一個單位的,因此首部最大長度是 15 * 4 = 60 字節。
  • 保留字段 (Reserved):占 6 位,未來可能有具體用途,目前默認值為0.
  • 控制位 (Control Bits):在三次握手和四次揮手中會經常看到 SYN、ACK 和 FIN 的身影,一共有 6 個標志位,它們表示的意義如下:

    • URG (Urgent Bit):值為 1 時,緊急指針生效
    • ACK (Acknowledgment Bit):值為 1 時,確認序號生效
    • PSH (Push Bit):接收方應盡快將這個報文段交給應用層
    • RST (Reset Bit):發送端遇到問題,想要重建連接
    • SYN (Synchronize Bit):同步序號,用于發起一個連接
    • FIN (Finish Bit):發送端要求關閉連接
  • 窗口大小 (Window): TCP的流量控制由連接的每一端通過聲明的窗口大小來提供。窗口大小為字節數,起始于確認序號字段指明的值,這個值是接收端正期望接收的字節。窗口大小是一個 16 bit 字段,單位是字節, 因而窗口大小最大為 65535 字節。
  • 檢驗和 (Checksum):功能類似于數字簽名,用于驗證數據完整性,也就是確保數據未被修改。檢驗和覆蓋了整個 TCP 報文段,包括 TCP 首部和 TCP 數據,發送端根據特定算法對整個報文段計算出一個檢驗和,接收端會進行計算并驗證。
  • 緊急指針 (Urgent Pointer):當 URG 控制位值為 1 時,此字段生效,緊急指針是一個正的偏移量,和序號字段中的值相加表示緊急數據最后一個字節的序號。 TCP 的緊急方式是發送端向另一端發送緊急數據的一種方式。
  • 選項 (Options):這一部分是可選字段,也就是非必須字段,最常見的可選字段是“最長報文大小 (MSS,Maximum Segment Size)”。
  • 有效數據部分 (Data):這部分也不是必須的,比如在建立和關閉 TCP 連接的階段,雙方交換的報文段就只包含 TCP 首部。

常見面試題 1:?TCP 建立連接為什么要三次握手而不是兩次?

  • 防止已過期的連接請求報文突然又傳送到服務器,因而產生錯誤

    在雙方兩次握手即可建立連接的情況下,假設客戶端發送 A 報文段請求建立連接,由于網絡原因造成 A 暫時無法到達服務器,服務器接收不到請求報文段就不會返回確認報文段,客戶端在長時間得不到應答的情況下重新發送請求報文段 B,這次 B 順利到達服務器,服務器隨即返回確認報文并進入 ESTABLISHED 狀態,客戶端在收到 確認報文后也進入 ESTABLISHED 狀態,雙方建立連接并傳輸數據,之后正常斷開連接。此時姍姍來遲的 A 報文段才到達服務器,服務器隨即返回確認報文并進入 ESTABLISHED 狀態,但是已經進入 CLOSED 狀態的客戶端無法再接受確認報文段,更無法進入 ESTABLISHED 狀態,這將導致服務器長時間單方面等待,造成資源浪費。

  • 三次握手才能讓雙方均確認自己和對方的發送和接收能力都正常

    第一次握手:客戶端只是發送處請求報文段,什么都無法確認,而服務器可以確認自己的接收能力和對方的發送能力正常;

    第二次握手:客戶端可以確認自己發送能力和接收能力正常,對方發送能力和接收能力正常;

    第三次握手:服務器可以確認自己發送能力和接收能力正常,對方發送能力和接收能力正常;

    可見三次握手才能讓雙方都確認自己和對方的發送和接收能力全部正常,這樣就可以愉快地進行通信了。

  • 告知對方自己的初始序號值,并確認收到對方的初始序號值

    TCP 實現了可靠的數據傳輸,原因之一就是 TCP 報文段中維護了序號字段和確認序號字段,也就是圖中的 seq 和 ack,通過這兩個字段雙方都可以知道在自己發出的數據中,哪些是已經被對方確認接收的。這兩個字段的值會在初始序號值得基礎遞增,如果是兩次握手,只有發起方的初始序號可以得到確認,而另一方的初始序號則得不到確認。

  • 常見面試題2:?TCP 建立連接為什么要三次握手而不是四次?

    答:相比上個問題而言,這個問題就簡單多了。因為三次握手已經可以確認雙方的發送接收能力正常,雙方都知道彼此已經準備好,而且也可以完成對雙方初始序號值得確認,也就無需再第四次握手了。

    常見面試題3:?有一種網絡攻擊是利用了 TCP 建立連接機制的漏洞,你了解嗎?這個問題怎么解決?

    答:在三次握手過程中,服務器在收到了客戶端的 SYN 報文段后,會分配并初始化連接變量和緩存,并向客戶端發送 SYN + ACK 報文段,這相當于是打開了一個“半開連接 (half-open connection)”,會消耗服務器資源。如果客戶端正常返回了 ACK 報文段,那么雙方可以正常建立連接,否則,服務器在等待一分鐘后會終止這個“半開連接”并回收資源。這樣的機制為 SYN洪泛攻擊 (SYN flood attack)提供了機會,這是一種經典的 DoS攻擊 (Denial of Service,拒絕服務攻擊),所謂的拒絕服務攻擊就是通過進行攻擊,使受害主機或網絡不能提供良好的服務,從而間接達到攻擊的目的。在 SYN 洪泛攻擊中,攻擊者發送大量的 SYN 報文段到服務器請求建立連接,但是卻不進行第三次握手,這會導致服務器打開大量的半開連接,消耗大量的資源,最終無法進行正常的服務。

    解決方法:SYN Cookies,現在大多數主流操作系統都有這種防御系統。SYN Cookies 是對 TCP 服務器端的三次握手做一些修改,專門用來防范 SYN 洪泛攻擊的一種手段。它的原理是,在服務器接收到 SYN 報文段并返回 SYN + ACK 報文段時,不再打開一個半開連接,也不分配資源,而是根據這個 SYN 報文段的重要信息 (包括源和目的 IP 地址,端口號可一個秘密數),利用特定散列函數計算出一個 cookie 值。這個 cookie 作為將要返回的SYN + ACK 報文段的初始序列號(ISN)。當客戶端返回一個 ACK 報文段時,服務器根據首部字段信息計算 cookie,與返回的確認序號(初始序列號 + 1)進行對比,如果相同,則是一個正常連接,然后分配資源并建立連接,否則拒絕建立連接。

    常見面試題4:?為什么 TCP 關閉連接為什么要四次而不是三次?

    答:服務器在收到客戶端的 FIN 報文段后,可能還有一些數據要傳輸,所以不能馬上關閉連接,但是會做出應答,返回 ACK 報文段,接下來可能會繼續發送數據,在數據發送完后,服務器會向客戶單發送 FIN 報文,表示數據已經發送完畢,請求關閉連接,然后客戶端再做出應答,因此一共需要四次揮手。

    常見面試題6:?客戶端為什么需要在 TIME-WAIT 狀態等待 2MSL 時間才能進入 CLOSED 狀態?

    答:按照常理,在網絡正常的情況下,四個報文段發送完后,雙方就可以關閉連接進入 CLOSED 狀態了,但是網絡并不總是可靠的,如果客戶端發送的 ACK 報文段丟失,服務器在接收不到 ACK 的情況下會一直重發 FIN 報文段,這顯然不是我們想要的。因此客戶端為了確保服務器收到了 ACK,會設置一個定時器,并在 TIME-WAIT 狀態等待 2MSL 的時間,如果在此期間又收到了來自服務器的 FIN 報文段,那么客戶端會重新設置計時器并再次等待 2MSL 的時間,如果在這段時間內沒有收到來自服務器的 FIN 報文,那就說明服務器已經成功收到了 ACK 報文,此時客戶端就可以進入 CLOSED 狀態了。

    常見面試題7:怎么解決tcp沾包?

    TCP是流協議,根本不存在所謂粘包一說。TCP是流協議,根本不存在所謂粘包一說。TCP保證發送方以什么順序發字節流,接收方就一定能按這個順序接收到。

    TCP是個"流"協議,所謂流,就是沒有界限的一串數據.大家可以想想河里的流水,是連成一片的,其間是沒有分界線的.但一般通訊程序開發是需要定義一個個相互獨立的數據包的,比如用于登陸的數據包,用于注銷的數據包.由于TCP"流"的特性以及網絡狀況,在進行數據傳輸時會出現以下幾種情況.
    假設我們連續調用兩次send分別發送兩段數據data1和data2,在接收端有以下幾種接收情況(當然不止這幾種情況,這里只列出了有代表性的情況).
    A.先接收到data1,然后接收到data2.
    B.先接收到data1的部分數據,然后接收到data1余下的部分以及data2的全部.
    C.先接收到了data1的全部數據和data2的部分數據,然后接收到了data2的余下的數據.
    D.一次性接收到了data1和data2的全部數據.

    對于A這種情況正是我們需要的,不再做討論.對于B,C,D的情況就是大家經常說的"粘包",就需要我們把接收到的數據進行拆包,拆成一個個獨立的數據包.為了拆包就必須在發送端進行封包.

    另:對于UDP來說就不存在拆包的問題,因為UDP是個"數據包"協議,也就是兩段數據間是有界限的,在接收端要么接收不到數據要么就是接收一個完整的一段數據,不會少接收也不會多接收.

    二.為什么會出現B.C.D的情況.
    "粘包"可發生在發送端也可發生在接收端.
    1.由Nagle算法造成的發送端的粘包:Nagle算法是一種改善網絡傳輸效率的算法.簡單的說,當我們提交一段數據給TCP發送時,TCP并不立刻發送此段數據,而是等待一小段時間,看看在等待期間是否還有要發送的數據,若有則會一次把這兩段數據發送出去.這是對Nagle算法一個簡單的解釋,詳細的請看相關書籍.象C和D的情況就有可能是Nagle算法造成的.
    2.接收端接收不及時造成的接收端粘包:TCP會把接收到的數據存在自己的緩沖區中,然后通知應用層取數據.當應用層由于某些原因不能及時的把TCP的數據取出來,就會造成TCP緩沖區中存放了幾段數據.

    三.怎樣封包和拆包.
    ?? 最初遇到"粘包"的問題時,我是通過在兩次send之間調用sleep來休眠一小段時間來解決.這個解決方法的缺點是顯而易見的,使傳輸效率大大降低,而且也并不可靠.后來就是通過應答的方式來解決,盡管在大多數時候是可行的,但是不能解決象B的那種情況,而且采用應答方式增加了通訊量,加重了網絡負荷. 再后來就是對數據包進行封包和拆包的操作.
    ??? 封包:
    封包就是給一段數據加上包頭,這樣一來數據包就分為包頭和包體兩部分內容了(以后講過濾非法包時封包會加入"包尾"內容).包頭其實上是個大小固定的結構體,其中有個結構體成員變量表示包體的長度,這是個很重要的變量,其他的結構體成員可根據需要自己定義.根據包頭長度固定以及包頭中含有包體長度的變量就能正確的拆分出一個完整的數據包.
    ??? 對于拆包目前我最常用的是以下兩種方式.
    ??? 1.動態緩沖區暫存方式.之所以說緩沖區是動態的是因為當需要緩沖的數據長度超出緩沖區的長度時會增大緩沖區長度.
    ??? 大概過程描述如下:
    ??? A,為每一個連接動態分配一個緩沖區,同時把此緩沖區和SOCKET關聯,常用的是通過結構體關聯.
    ??? B,當接收到數據時首先把此段數據存放在緩沖區中.
    ??? C,判斷緩存區中的數據長度是否夠一個包頭的長度,如不夠,則不進行拆包操作.
    ??? D,根據包頭數據解析出里面代表包體長度的變量.
    ??? E,判斷緩存區中除包頭外的數據長度是否夠一個包體的長度,如不夠,則不進行拆包操作.
    ??? F,取出整個數據包.這里的"取"的意思是不光從緩沖區中拷貝出數據包,而且要把此數據包從緩存區中刪除掉.刪除的辦法就是把此包后面的數據移動到緩沖區的起始地址.

    看看人家http怎么解決的?

    header里有Content-Length: 12345指定了body的大小,body才是文件本身。數據是100%正確的

    參考文獻:https://www.zhihu.com/question/20210025

    https://blog.csdn.net/zhangxinrun/article/details/6721495

    https://segmentfault.com/a/1190000022410446

    https://blog.51cto.com/jinlong/2065461

    總結

    以上是生活随笔為你收集整理的计算机网络是如何通信的【二】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。