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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

TCP协议通讯流程(三次握手及四次挥手)

發布時間:2024/4/11 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP协议通讯流程(三次握手及四次挥手) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

TCP協議通訊流程(三次握手及四次揮手)

文章目錄

  • TCP協議通訊流程(三次握手及四次揮手)
    • 一、服務器端
    • 二、客戶端
    • 三、三次握手四次揮手
    • 三、具體流程
    • 四、相關注意事項

一、服務器端

  • 調用socket函數,創建一個socket(文件描述符)操作句柄
  • 調用bind函數,把剛創建的socket文件描述符 和 ip及端口 綁定在一起,注意一個進程可以綁定多個端口號,但是一個端口號只能被一個進程綁定bind中進程和端口的關系
  • 調用listen函數,對socket文件描述符進行監聽(首先listen會在進程地址空間中維護一個緩沖區,如果有客戶鏈接進來,就把其放進緩沖區)
  • 進入主循環,循環處理客戶端的請求(死循環)
  • 調用accept函數并阻塞,等待客戶端進來鏈接(在listen緩沖區中去出),accept成功就返回一個新的socket文件描述符操作句柄,在多進程或多線程等情況下,舊的socket在父進程中返回,繼續accept,子進程拿到newsocket對客戶進行操作(下面的操作都是newsocket)
  • 調用recv函數,接受客戶端發送的請求
  • 對客戶端發送來的請求在函數內部進行處理
  • 調用send函數,把處理結果返回給客戶端。
  • 關閉socket
  • 二、客戶端

  • 調用socket函數,創建一個socket(文件描述符)操作句柄
  • 調用connect函數,向服務器發送鏈接請求
  • 進入主循環,服務器和客戶端可能進行多次交互,不止一次
  • 調用send函數,把請求數據發送給服務器
  • 調用recv函數,接受服務器返回的結果
  • 關閉socket
  • 三、三次握手四次揮手

    • 1 . 三次握手

    • 在客戶端向服務器建立鏈接的過程中:客戶端首先創建自己的socket

    • 調用connect發起鏈接服務器的請求

    • 其中connect函數會發出SYN段并阻塞等待服務器的響應 (第一次)

    • 服務器收到客戶端的鏈接請求SYN,會應答客戶端,向客戶端發送一個SYN-ACK,表示同意建立連接請求 (第二次)

    • 客戶端收到服務器端的SYN-ACK后會從connect返回,同時向服務器端再應答一個ACK段; (第三次

    • 2.四次揮手

    • 在數據傳輸的過程中:建立連接后,TCP協議提供全雙工的通信服務(全雙工:在同一條鏈接中,同一時刻通信雙方都可以寫數據)。

    • 服務器在調用socket創建出socket文件描述符后,再調用bind綁定ip及端口號,服務器在調用accept獲取客戶端,調用完accept后立即調用recv函數(阻塞,跟read讀取管道一樣)

    • 在這個時間客戶端調用send函數向服務器端發送請求(和write管道一樣),服務器收到從recv返回的請求,在對客戶端的請求進行處理,在這期間客戶端調用send函數阻塞等待

    • 服務器端調再用send把響應結果發給客戶端,再次調用recv讀取客戶端請求

    • 在斷開鏈接的過程中(一般都是客戶端主動斷開鏈接,服務器畢竟不是為一個客戶服務):如果客戶端不在請求了,就會調用close函數關閉鏈接,客戶端就會向服務器端發送一個FIN段,表示我要斷開鏈接了 (第一次)

    • 此時服務器端在響應完客戶端的請求后,沒有在收到客戶端的請求,一直阻塞在recv處,此時收到客戶端發送的FIN后,會向客戶端回應一個ACK,同時recv會返回0 (第二次)

    • 服務器端recv返回后,服務器端就直到客戶端要關閉鏈接了,也調用close函數關閉連接,再向客戶端發送一個FIN (第三次)

    • 客戶端收到ACK和FIN后,再向服務器端發送一個ACK (第四次)

    三、具體流程

    • 服務端狀態轉化:
    • [CLOSED -> LISTEN] 服務器端調用listen后進入LISTEN狀態, 等待客戶端連接;
    • [LISTEN -> SYN_RCVD] 一旦監聽到連接請求(同步報文段), 就將該連接放入內核等待隊列中, 并向客戶端發送SYN確認報文.
    • [SYN_RCVD -> ESTABLISHED] 服務端一旦收到客戶端的確認報文ACK, 就進入ESTABLISHED狀態, 可以進行讀寫數據了
    • [ESTABLISHED -> CLOSE_WAIT] 當客戶端主動關閉連接(調用close), 服務器會收到結束報文段, 服務器返回確認報文段ACK并進入CLOSE_WAIT;
    • [CLOSE_WAIT -> LAST_ACK] 進入CLOSE_WAIT后說明服務器準備關閉連接(需要處理完之前的數據); 當服務器真正調用close關閉連接時, 會向客戶端發送FIN, 此時服務器進入LAST_ACK狀態, 等待最后一個ACK到來(這個ACK是客戶端確認收到了FIN)
    • [LAST_ACK -> CLOSED] 服務器收到了對FIN的ACK, 徹底關閉連接
    • 客戶端狀態變化
    • [CLOSED -> SYN_SENT] 客戶端調用connect, 發送同步報文段;
    • [SYN_SENT -> ESTABLISHED] connect調用成功, 則進入ESTABLISHED狀態冰箱服務器端發送一個ACK, 開始讀寫數據;
    • [ESTABLISHED -> FIN_WAIT_1] 客戶端主動調用close時, 向服務器發送結束報文段FIN, 同時進入FIN_WAIT_1;
    • [FIN_WAIT_1 -> FIN_WAIT_2] 客戶端收到服務器對結束報文段的確認, 則進入FIN_WAIT_2, 開始等待服務器的結束報文段;
    • [FIN_WAIT_2 -> TIME_WAIT] 客戶端收到服務器發來的結束報文段, 進入TIME_WAIT, 并發出LAST_ACK;
    • [TIME_WAIT -> CLOSED] 客戶端要等待一個2MSL(MaxSegment Life, 報文最大生存時間)的時間, 才會進入CLOSED狀態

    四、相關注意事項

    • 1 . 客戶端為什么不需要bind?

    • 首先服務器端bind是因為如果客戶端要訪問服務器端,就必須要服務器端端“地址”,也就是ip+端口號,這樣客戶端才能找到服務器,進行通信

    • 如果服務器端不進行bind操作,那么操作系統就會隨機分配端口號給服務器,那么客戶端就不能和服務器端進行通信。

    • 而客戶端為什么不需要bind,是因為如果客戶端bind一個ip + 端口,那么如果一個pc上有多個用戶,那么bind同一個端口就會出錯(如果一臺pc上只有一個用戶也是可以bind)。

    • 2 . 為什么要進行三次握手?

    • 為了防止無效的連接請求報文到達服務器而引起錯誤。

    • TCP發起建立連接的一方不會一直等待對方的回復,如果超時,他再次發起這個請求,上一個作廢。

    • 假設A給服務器發送了一個請求,但是由于網絡原因遲遲沒有到達B服務器。由于一直沒收到服務器端的回復確認,所以就進行超時重傳,上個就舍棄了。

    • 然后新的請求很快的到達了B服務器,然后B服務器也很快的進行了響應,如果是兩次握手的話,這樣就建立了連接

    • 但是上次因網絡問題遲遲未到的第一個請求這時到達了B服務器,服務器依然會當成新的連接請求進行響應,(服務器只要響應,第二次握手就完成了)這時又會建立連接,這就會出現建立了兩個連接的局面,

    • 然后這就會出現很多問題,例如服務器端認為完成了握手,可以發送數據了,于是一直處于等待數據狀態,而發送端不理睬服務器端發來的請求(因為發送端的那個請求早就被清除了),不去發送數據,后果就是服務器一直等,這樣就會浪費很多服務器資源

    • 如果是三次握手的話,就會避免這個問題,因為比如第二次的新請求到達時,發送端就會又給服務器端發送個確認請求,表示接收到了,這樣遲到的那個請求到達服務器端,然后返回到發送端時,發送端并不會響應。然后這個連接并不會建立,服務器也就不會白白等待。

    • 3.為什么要進行四次揮手?

    • 確保數據能夠完整傳輸。

    • 當被動方收到主動方的FIN報文通知時,它僅僅表示主動方沒有數據再發送給被動方了。

    • 但未必被動方所有的數據都完整的發送給了主動方,所以被動方不會馬上關閉SOCKET,它可能還需要發送一些數據給主動方后,(按照常理的話,第二次和第三次揮手應該一起回復FIN和ACK的,但是因為服務器端可能有數據沒發完,所以不能也立刻去主動申請關閉,所以要把ACK和FIN分開)再發送FIN報文給主動方,告訴主動方同意關閉連接,所以這里的ACK報文和FIN報文多數情況下都是分開發送的。

    • 4.timewite的產生的原因及作用?

    • 為實現TCP全雙工連接的可靠釋放

    • 假設發起主動關閉的一方(client)最后發送的ACK在網絡中丟失,由于TCP協議的重傳機制,執行被動關閉的一方(server)將會重發其FIN

    • 在該FIN到達client之前,client必須維護這條連接狀態,也就說這條TCP連接所對應的資源(client方的local_ip,local_port)不能被立即釋放或重新分配

    • 直到另一方重發的FIN達到之后,client重發ACK后,經過2MSL時間周期沒有再收到另一方的FIN之后,該TCP連接才能恢復初始的CLOSED狀態。

    • 如果主動關閉一方不維護這樣一個TIME_WAIT狀態,那么當被動關閉一方重發的FIN到達時,主動關閉一方的TCP傳輸層會用RST包響應對方,這會被對方認為是有錯誤發生,然而這事實上只是正常的關閉連接過程,并非異常

    • 確保第四次握手時發送方發送的ACK可以到達接收方 如果2MSL時間內沒有收到,則接收方會進行重發

    • 確保當前連接的所有報文都已經過期(每個具體TCP實現必須選擇一個報文段最大生存時間MSL。它是任何報文段被丟棄前在網絡內的最長時間,2MSL足夠使所有報文過期了)

    • 5.理解close_wait狀態?

    • close_wait狀態介紹:

    • 客戶端主動關閉連接,服務器接收到客戶端的FIN,但是還沒有發送自己的FIN,此時的狀態為close_wait狀態,大量的close_wait狀態拖累服務器性能

    • close_wait產生的原因:

    • 某種情況下客戶端關閉了連接,但是我方忙于讀寫,沒有關閉連接

    • 解決方法:

    • 思想:檢查出客戶端已經關閉的連接,他之所以會出現這種問題,肯定是服務器端的連接釋放的代碼存在問題

    1.當服務器讀寫失敗時,可以選擇關閉連接2.定期向連接發送詢問數據,檢查收到的回復數據包(Heart-Beat線程發送指 定格式的心跳數據包)3.修改keep-live參數(超時時間,tcp檢查間隔時間:keeplive探測包 發送的間隔,tcp檢查次數:如果對方不予應答,探測包發送的次數)

    總結

    以上是生活随笔為你收集整理的TCP协议通讯流程(三次握手及四次挥手)的全部內容,希望文章能夠幫你解決所遇到的問題。

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