成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Python中TCP協(xié)議的三次握手與四次揮手是什么-創(chuàng)新互聯(lián)

本篇內容介紹了“Python中TCP協(xié)議的三次握手與四次揮手是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

在章貢等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網站設計、成都網站建設 網站設計制作按需網站策劃,公司網站建設,企業(yè)網站建設,成都品牌網站建設,營銷型網站建設,成都外貿網站建設,章貢網站建設費用合理。

一、TCP、UDP 協(xié)議的區(qū)別

在介紹這兩者的區(qū)別之前,我們要需要了解一個概念:TCP/IP 協(xié)議族。定義如下:

目前 Internet(因特網)使用的主流協(xié)議族是 TCP/IP 協(xié)議族,它是一個分層、多協(xié)議的通信體系 《Linux高性能編程》

提取關鍵詞:分層、多協(xié)議和通信。也就是說,它有多個層次,每個層次有不同的協(xié)議,這些層次之間通過協(xié)議相互協(xié)作,最終達到網絡通信的目的。

說到分層,應該不會很陌生,TCP/IP 協(xié)議族是一個四層協(xié)議系統(tǒng),自底而上分別是:數據鏈接層、網絡層、傳輸層、應用層。我們這里要說到的 TCP 和 UDP 協(xié)議屬于傳輸層。(各層的作用及相關協(xié)議這里暫時先不做介紹)

下面我們回到標題:TCP、UDP 協(xié)議的區(qū)別,總結起來這個問題的答案要點如下:

1、首頁它們倆都是傳輸層的協(xié)議,而所謂“傳輸層”,它是為兩臺主機提供端到端的通信,即從 A <-> B 。

2、TCP 協(xié)議可靠,UDP 協(xié)議不可靠。可靠即指數據由 A 發(fā)送到 B,是否能確保數據真的有送達到 B。TCP 協(xié)議使用 超時重傳、數據確認等方式來確保數據包被正確地發(fā)送至目的端,而 UDP 協(xié)議無法保證數據從發(fā)送端正確傳送到目的端,如果數據在傳輸過程中丟失、或者目的端通過數據檢驗發(fā)現(xiàn)數據錯誤,則 UDP 協(xié)議只是簡單地通知應用程序發(fā)送失敗,對于 TCP 協(xié)議擁有的超時重傳、數據確認等需要應用程序自己來處理這些邏輯。

3、TCP 是面向連接的,UDP 是無連接的。這也比較好理解,因為 TCP 連接才需要“三次握手,四次揮手”。

4、TCP 服務是基于流的,而 UDP 是基于數據報的,基于流的數據沒有邊界(長度)限制,而基于數據報的服務,每個 UDP 數據報都有一個長度,接收端必須以該長度為最小單位將其所有內容一次性讀出。

5、當發(fā)送方多次執(zhí)行寫操作時,TCP 模塊會先將這些數據放入 TCP 發(fā)送緩沖區(qū)中,當 TCP 模塊真正開始發(fā)送數據時,發(fā)送緩沖區(qū)中這些等待發(fā)送的數據可能被封裝成一個或多個 TCP 報文段發(fā)出,因此,TCP 模塊發(fā)出的 TCP 報文段的個數與應用程序執(zhí)行的寫操作次數是沒有固定數量關系的。同樣,當接收端收到一個或多個 TCP 報文段后,TCP 模塊將這些數據按照序號(序號說明見下面 的 TCP 頭部結構)依次放入 TCP 接收緩沖區(qū)中,并通知應用程序讀取數據。接收端可選擇一次或者分多次將數據從緩沖區(qū)中讀出(這取決于用戶指定的應用程序讀緩沖區(qū)的大?。?。因此,接收端讀取數據的次數與發(fā)送端發(fā)出多少個報文段個數也沒有固定的數量關系??偨Y來說,即**對于 TCP 連接,發(fā)送端執(zhí)行的寫操作次數與接收端執(zhí)行的讀操作次數之間沒有任何數據關系,這也是基于流服務的特點。**而對于 UDP 服務,發(fā)送端每執(zhí)行一次寫操作,就會將其封裝成一個 UDP 數據報并發(fā)送之,同時接收端必須根據發(fā)送的進行讀,否則就會丟包。因此,對于 UDP 連接,發(fā)送端寫的次數據與讀的次數是一致的,這也是基于數據報的服務的特點。

6、TCP 的連接是一對一的,所以如果是基于廣播或者多播的的應用程序不能使用 TCP,而 UDP 則非常適合廣播和多播。

總結一句定義:

TCP 協(xié)議(Transmission Control Protocal,傳輸控制協(xié)議)為應用層提供可靠的、面向連接的、基于流的服務。而 UDP 協(xié)議(User Datagram Protocal,用戶數據報協(xié)議)則與 TCP 協(xié)議完全相反,它為應用層提供不可靠、無連接和基于數據報的服務。

二、TCP 頭部結構

TCP 報文結構分為頭部部分和數據部分,為什么需要了解 TCP 頭部結構,因為在后面“三次握手與四次揮手”里會用到頭部結構里的標志位。簡單了解下對理解后面的過程有一定的好處。

下面一一說明每個的作用:

16位源端口號與目的端口號,這個比較好理解,就不過多解釋。

32位序號:在建立連接(或者關閉)的過程,這個序號是用來做占位,當 A 發(fā)送連接請求到 B,這個時候會帶上一個序號(隨機值,稱為 ISN),而 B 確認連接后,會把這個序號 +1 返回,同時帶上自己的充號。當建立連接后,該序號為生成的隨機值 ISN 加上該段報文段所攜帶的數據的第一個字節(jié)在整個字節(jié)流中的偏移量。比如,某個 TCP 報文段發(fā)送的數據是字節(jié)流中的第 100 ~ 200 字節(jié),那該序號為 ISN + 100。所以總結起來說明建立連接(或者關閉)時,序號的作用是為了占位,而連接后,是為了標記當前數據流的第一個字節(jié)。

4位頭部長度:標識 TCP 頭部有多少個 32 bit 字,因為是 4位,即 TCP 頭部大能表示 15,即最長是 60 字節(jié)。即它是用來記錄頭部的大長度。

6位標志位,包括:

URG 標志:表示緊急指針是否有效。

ACK 標志:確認標志。通常稱攜帶 ACK 標志的 TCP 報文段為確認報文段。

PSH 標志:提示接收端應該程序應該立即從 TCP 接收緩沖區(qū)中讀走數據,為接收后續(xù)數據騰出空間(如果不讀走,數據就會一直在緩沖區(qū)內)。

RST 標志:表示要求對方重新建立連接。通常稱攜帶 RST 標志的 TCP 報文段為復位報文段。

SYN 標志:表示請求建立一個連接。通常稱攜帶 SYN 標志的 TCP 報文段稱為同步報文段。

FIN 標志:關閉標志,通常稱攜帶 FIN 標志的 TCP 報文段為結束報文段。

這些標志位說明了當前請求的目的,即要干什么。

16 位窗口大?。罕硎井斍?TCP 接收緩沖區(qū)還能容納多少字節(jié)的數據,這樣發(fā)送方就可以控制發(fā)送數據的速度,它是 TCP 流量控制的一個手段。

16 位校驗和:驗證數據是否損壞,通過 CRC 算法檢驗。這個校驗不僅包括 TCP 頭部,也包括數據部分。

16 位緊急指針:正的偏移量,它和序號字段的值相加表示最后一個緊急數據的下一字節(jié)的序號。TCP 的緊急指針是發(fā)送端向接收端發(fā)送緊急數據的方法。

TCP 頭部選項:可變長的可選信息,這部分最多包含 40 字節(jié),因為 TCP 頭部最長是 60 字節(jié),所以固定部分占 20 字節(jié)。這里不做詳細介紹,可以參考《Linux高性能編程》3.2.2

三、三次握手與四次揮手過程詳解

畫圖

先來解釋三次握手過程:

1、發(fā)送端發(fā)送連接請求,6位標志為 SYN,同時帶上自己的序號(此時由于不傳輸數據,所以不表示字節(jié)的偏移量,只是占位),比如是 223。

2、接收端接到請求,表示同意連接,發(fā)送同意響應,帶上 SYN + ACK 標志位,同時將確認序號為 224(發(fā)送端序號加1),并帶上自己的序號(此時同樣由于不傳輸數據,所以不表示字節(jié)的偏移量,只是占位),比如是 521。

3、發(fā)送端接收到確認信息,再發(fā)回給接收端,表示我已接受到你的確認信息,此時標志仍為 ACK,確認序號為 522。

涉及到的問題:為什么是三次握手,而不是四次或者兩次?

首先解釋為什么不是四次。四次的過程是這樣的:

發(fā)送方:我要連你了。

接收方:好的。

接收方:我準備好了,你連吧。

發(fā)送方:好的。

顯然接收方準備好連接并同意連接是可以合并的,這樣可以提高連接的效率。

再來,我們解釋為什么不是兩次。其實也比較好理解,我們知道 TCP 是全雙工通信的,同時也是可靠的,連接和關閉都是兩邊都要執(zhí)行才算真正的完成,同時還需要確保兩端都已經執(zhí)行了連接或者關閉。如果只有兩次,過程是這樣的:

發(fā)送方:我要連你了。

接收方:好的。

很明顯,接收方并不知道也不能保證發(fā)送方一定接收到 “好的” 這條信息,一旦接收方真的沒有收到這條信息,就會出現(xiàn)接收收“單方面連接”的情況,這個時候發(fā)送方就會一直重試發(fā)送連接請求,直到真正收到 “好的” 這條信息之后才算連接完成。而對于三次,如果發(fā)送方沒有等待到你回復確認,它是不會真正處于連接狀態(tài)的,它會重試確認請求。

接著我們來看看四次揮手過程:

1、發(fā)送方發(fā)送關閉請求,標志位為:FIN,同時也會帶上自己的序號(此時同樣由于不傳輸數據,所以不表示字節(jié)的偏移量,只是占位)。

2、接收方接到請求后,回復確認:ACK,同時確認序號為請求序號加1。

3、接收方也決定關閉連接,發(fā)送關閉通知,標志位為 FIN,同時還會帶上第2步中的確認信息,即 ACK,以及確認序號和自己的序號。

4、發(fā)送方回復確認信息:ACK,接收方序號加1。

涉及到的問題:為什么需要四次握手,不是三次?

三次的過程是這樣的:

發(fā)送方:我不再給你發(fā)送數據了。

接收方:好的,我也不給你發(fā)了。

發(fā)送方:好的,拜拜。

這是因為當接收方收到關閉請求后,它能立馬響應的就是確認關閉,它這里確認的是接收方的關閉,即發(fā)送方不再發(fā)數據給接收方了,但他還是可以接收接收方發(fā)給他的數據。而接收方是否需要關閉“發(fā)送數據給發(fā)送方”這條通道,取決于操作系統(tǒng)。操作系統(tǒng)也有可能 sleep 個幾秒再關閉,如果合并成三次,就可能造成接收方不能及時收到確認請求,可能造成超時重試等情況。因此需要四次。

四、什么是 TIME_WAIT 狀態(tài)

首先,我們來看一段代碼(說了這么多理論,終于要看點代碼了)。這里舉一個 python 簡單的使用 socket 進行 tcp 通信的示例:

服務端:

socket_server_test.py
# -*- coding: utf-8 -*-
"""
@Time : 2019/6/26 下午4:58
@Author : Demon
@File : socket_server_test.py
@Desc : 
"""
import socket
HOST = '127.0.0.1' # 標準的回環(huán)地址 (localhost)
PORT = 9999 # 監(jiān)聽的端口 (非系統(tǒng)級的端口: 大于 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 第三個參數,如果為0,也不可復用
# 第三個如果為1,可以復用
# s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
 print('Connected by', addr)
 while True:
 data = conn.recv(1024)
 print("data:", data)
 if data:
 print("close")
 s.close()
 break
 conn.sendall(data)

客戶端:

# -*- coding: utf-8 -*-
"""
@Time : 2019/6/26 下午4:55
@Author : yrr
@File : socket_client_test.py
@Desc : 測試 self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
"""
import socket
HOST = '127.0.0.1' # 服務器的主機名或者 IP 地址
PORT = 9999 # 服務器使用的端口
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))

執(zhí)行效果:

我們會發(fā)現(xiàn),當我們服務端主動關閉時,如果我們再次運行這個程序,會報錯誤說端口仍然被占用。這就很奇怪了,明明已經關閉了連接,為什么還會占用著端口呢?我們使用 netstat -an|grep 9999 命令查看,發(fā)現(xiàn)當前這個連接處于 TIME_WAIT 狀態(tài)。

我們來說下 TIME_WAIT 狀態(tài)。即當一方斷開連接后,它并沒有直接進入 CLOSED 狀態(tài),而是轉移到 TIME_WAIT 狀態(tài),在這個狀態(tài),需要等待 2MSL(Maximum Segment Life,報文段大生存時間)的時間,才能完全關閉。

涉及問題:

1、為什么需要有 TIME_WAIT 狀態(tài)存在?

簡單來說有兩點原因如下:

a. 當最后發(fā)送方發(fā)出確認信息后,仍然不能保證接收方能收到信息,萬一沒收到,那接收方就會重試,而此時發(fā)送方已經真正關閉了,就接受不到請求了。

b. 如果發(fā)送方在發(fā)出確認信息后就關閉了,在接收方接到確認信息的過程中,發(fā)送方是有可能再次發(fā)出連接請求的,那這個時候就亂套了。剛連接完,又收到確認關閉的信息。

2、為什么時長是 2MSL 呢?

這個其實也比較好理解,所以我發(fā)送確認信息,到達最長時間是 MSL,而你如果沒接受到,再重試,時間最長也是 MSL,那我等 2MSL,如果還沒收到請求,證明你真的已經正常收到了。

正因為我們有這個 TIME_WAIT 狀態(tài),所以通常我們說是客戶端先關閉,一般不會讓服務器端先關閉。那如何避免出現(xiàn)關閉后端口被占用的情況(即上面代碼示例問題怎么解決)呢?很簡單,加一行代碼即可實現(xiàn):

# socket.SO_REUSEADDR 表示 close 后端口可復用
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

“Python中TCP協(xié)議的三次握手與四次揮手是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)-成都網站建設公司網站,小編將為大家輸出更多高質量的實用文章!

名稱欄目:Python中TCP協(xié)議的三次握手與四次揮手是什么-創(chuàng)新互聯(lián)
當前地址:http://jinyejixie.com/article40/dhdceo.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供網站建設、搜索引擎優(yōu)化用戶體驗、網站設計公司、網站導航、動態(tài)網站

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都網頁設計公司
巨鹿县| 巫溪县| 永丰县| 宜昌市| 伽师县| 鄂托克前旗| 临海市| 广平县| 德保县| 荥阳市| 乡宁县| 桑植县| 墨江| 观塘区| 洪湖市| 黑山县| 江安县| 长丰县| 云安县| 西安市| 克拉玛依市| 鹤山市| 比如县| 贺兰县| 彩票| 伊金霍洛旗| 进贤县| 灵宝市| 龙游县| 包头市| 宝山区| 二手房| 疏勒县| 孟州市| 阿鲁科尔沁旗| 确山县| 桦南县| 阜康市| 威海市| 柏乡县| 龙门县|