Python入門【TCP建立連接的三次握手、 TCP斷開連接的四次揮手、套接字編程實戰、 TCP編程的實現、TCP雙向持續通信】(二十七)

👏作者簡介:大家好,我是愛敲代碼的小王,CSDN博客博主,Python小白
📕系列專欄:python入門到實戰、Python爬蟲開發、Python辦公自動化、Python數據分析、Python前后端開發
📧如果文章知識點有錯誤的地方,請指正!和大家一起學習,一起進步👀
🔥如果感覺博主的文章還不錯的話,請👍三連支持👍一下博主哦
🍂博主正在努力完成2023計劃中:以夢為馬,揚帆起航,2023追夢人

🔥🔥🔥 python入門到實戰專欄:從入門到實戰?

🔥🔥🔥 Python爬蟲開發專欄:從入門到實戰

🔥🔥🔥?Python辦公自動化專欄:從入門到實戰

🔥🔥🔥 Python數據分析專欄:從入門到實戰

🔥🔥🔥 Python前后端開發專欄:從入門到實戰

目錄

TCP建立連接的三次握手

?TCP斷開連接的四次揮手

?數據包與處理流程

?數據包處理流程

?套接字編程實戰

?UDP編程介紹

?UDP編程的實現

持續通信

TCP編程介紹

?TCP編程的實現

TCP雙向持續通信

?結合多線程實現TCP雙向傳送(自由聊天)


TCP建立連接的三次握手

?TCP是面向連接的協議,也就是說,在收發數據前,必須和對方建立可靠的連接。 一個TCP連接必須要經過三次“對話”才能建立起來,其中的過程非常復雜, 只簡單的描述下這三次對話的簡單過 程:

1)主機A向主機B發出連接請求:“我想給你發數據,可以嗎?”,這是第一次對話;

2)主機B向主機A發送同意連接和要求同步 (同步就是兩臺主機一個在發送,一個在接收,協調工作)的數據包 :“可以,你什么時候 發?”,這是第二次對話;

3)主機A再發出一個數據包確認主機B的要求同步:“我現在就發, 你接著吧!”, 這是第三次握手。 三次“對話”的目的是使數據包的發送和接收同步, 經過三次“對話” 之后,主機A才向主機B正式發送數據。

?

?

?1、第一步,客戶端發送一個包含SYN即同步(Synchronize)標志的TCP報文,SYN同步報文會指明客戶端使用的端口以及TCP連接的初始序號。

2、第二步,服務器在收到客戶端的SYN報文后,將返回一個SYN+ACK的報文,表示客戶端的請求被接受,同時TCP序號被加一,ACK即確認(Acknowledgement)

3、第三步,客戶端也返回一個確認報文ACK給服務器端,同樣TCP序列號被加一,到此一個TCP連接完成。然后才開始通信的第二步:數據處理。

這就是所說的TCP的三次握手(Three-way Handshake)。

?為什么TCP協議有三次握手,而UDP協議沒有?

??? 因為三次握手的目的是在client端和server端建立可靠的連接。保證雙方發送的數據對方都能接受到,這也是TCP協議的被稱為可靠的數據傳輸協議的原因。而UDP就不一樣,UDP不提供可靠的傳輸模式,發送端并不需要得到接收端的狀態,因此 UDP協議就用不著使用三次握手。

?TCP斷開連接的四次揮手

?TCP建立連接要進行3次握手,而斷開連接要進行4次:

第一次: 當主機A完成數據傳輸后,將控制位FIN置1,提出停止TCP連接的請求 ;

第二次: 主機B收到FIN后對其作出響應,確認這一方向上的TCP連接將關閉,將ACK置1;

第三次: 由B 端再提出反方向的關閉請求,將FIN置1 ;

第四次: 主機A對主機B的請求進行確認,將ACK置1,雙方向的關閉結束.。

?由TCP的三次握手和四次斷開可以看出,TCP使用面向連接的通信方式, 大大提高了數據通信的可靠性,使發送數據端和接收端在數據正式傳輸前就有了交互, 為數據正式傳輸打下了可靠的基礎。

?數據包與處理流程

什么是數據包

通信傳輸中的數據單位,一般也稱“數據包”。在數據包中包括: 包、幀、數據包、段、消息。

網絡中傳輸的數據包由兩部分組成:一部分是協議所要用到的首部,另一部分是上一層傳過來的數據。首部的結構由協議的具體規范詳細定義。在數據包的首部,明確標明了協議應該如何讀取數 據。反過來說,看到首部,也就能夠了解該協議必要的信息以及所要處理的數據。包首部就像協議的臉。

?

?數據包處理流程

?套接字編程實戰

socket編程介紹

TCP協議和UDP協議是傳輸層的兩種協議。Socket是傳輸層供給應用層的編程接口,所以Socket編程就分為TCP編程和UDP編程兩類。

?Socket編程封裝了常見的TCP、UDP操作,可以實現非常方便的網絡編程。

?socket()函數介紹

在Python語言標準庫中,通過使用socket模塊提供的socket對象, 可以在計算機網絡中建立可以互相通信的服務器與客戶端。在服務器端需要建立一個socket對象,并等待客戶端的連接。客戶端使用socket對象與服務器端進行連接,一旦連接成功,客戶端和服務器端就可以進行通信了。

???上圖中,我們可以看出socket通訊中,發送和接收數據,都是通過操作系統控制網卡來進行。因此,我們在使用之后,必須關閉socket。

?在Python 中,通常用一個Socket表示“打開了一個網絡連接”,語法格式如下:

socket.socket([family[, type[, proto]]])

family : 套接字家族可以使 AF_UNIX 或者 AF_INET

AF 表示ADDRESS FAMILY 地址族

AF_INET(又稱 PF_INET)是 IPv4 網絡協議的套接字類型;而 AF_UNIX 則是 Unix 系統本地通信

?type : 套接字類型可以根據是面向連接的還是非連接分為 SOCK_STREAM SOCK_DGRAMprotocol : 一般不填,默認為0。

Socket主要分為面向連接的Socket和無連接的Socket。 無連接Socket的主要協議是用戶數據報協議,也就是常說的UDP, UDP Socket的名字是 SOCK_DGRAM 。創建套接字UDP/IP套接字,可以 調用 socket.socket() 。示例代碼如下: udpSocket=socket.socket (AF_INET,SOCK_DGRAM)

?socket對象的內置函數和屬性

在Python語言中socket對象中,提供如表所示的內置函數。

?

?UDP編程介紹

UDP協議時,不需要建立連接,只需要知道對方的IP地址和端口 號,就可以直接發數據包。但是,能不能到達就不知道了。雖然用 UDP傳輸數據不可靠,但它的優點是和TCP比,速度快,對于不要求可靠到達的數據,就可以使用UDP協議。

創建Socket時, SOCK_DGRAM 指定了這個Socket的類型是UDP。綁定端口和TCP一樣,但是不需要調用 listen() 方法,而是直接接收來自任何客戶端的數據。 recvfrom() 方法返回數據和客戶端的地址與端口,這樣,服務器收到數據后,直接調用 sendto() 就可以把數據用UDP發給客戶端。

?UDP編程的實現

【示例】UDP接收數據

#coding=utf-8
from socket import *
s = socket(AF_INET, SOCK_DGRAM) #創建套接字
#綁定接收信息端口
s.bind(('127.0.0.1', 8888))  #綁定一個端口,ip地址和端?號
print("等待接收數據!")
redata = s.recvfrom(1024)  #1024表示本次接收的最?字節數
print(redata)
print(f'收到遠程信息:{redata[0].decode("gbk")}, from {redata[1]}')
s.close()

【示例】UDP發送數據

from socket import *
s = socket(AF_INET, SOCK_DGRAM) #創建套接字
addr = ('127.0.0.1', 8888) #準備接收方地址
data = input("請輸入:")
#發送數據時,python3需要將字符串轉成byte
s.sendto(data.encode('gbk'),addr) #默認的網絡助手使用的編碼是gbk
s.close()

持續通信

【示例】UDP接收數據

#coding=utf-8
from socket import *
s = socket(AF_INET,SOCK_DGRAM)  #創建UDP類型的套接字
s.bind(("127.0.0.1",8888))  #綁定端口,ip可以不寫
print("等待接收數據!")
while True:recv_data = s.recvfrom(1024)    #1024表示本次接收的最大字節數recv_content = recv_data[0].decode('gbk')print(f"收到遠程信息:{recv_content},from {recv_data[1]}")if recv_content == "88":print("結束聊天!")break
s.close()

【示例】UDP發送數據

#coding=utf-8
from socket import *
s = socket(AF_INET,SOCK_DGRAM)  #創建UDP類型的套接字
addr = ("127.0.0.1",8888)
while True:data = input("請輸入:")s.sendto(data.encode("gbk"),addr)if data == "88":print("結束聊天!")break
s.close()

結合多線程實現UDP雙向自由通信

UDP 不同于 TCP,不存在請求連接和受理過程,因此在某種意義上無法明確區分服務器端和客戶端,只是因為其提供服務而稱為服務器端。

?如下服務端、客戶端代碼幾乎一模一樣,注意接收和發送端口對應,即可。

?【示例】UDP實現多線程服務端

#coding=utf-8
from socket import *
from threading import Thread
udp_socket=socket(AF_INET,SOCK_DGRAM)
#綁定接收信息端口
udp_socket.bind(('127.0.0.1',8989))
#不停接收
def recv_data():while True:redata = udp_socket.recvfrom(1024)print(f'收到信息: {redata[0].decode("gbk")}, from {redata[1]}')
#不停發送
def send_data():while True:data=input('輸入信息:')addr=('127.0.0.1',8080)udp_socket.sendto(data.encode('gbk'),addr)
if __name__=='__main__':# 創建兩個線程t1=Thread(target=send_data)t2=Thread(target=recv_data)t2.start()t1.start()t1.join()t2.join()

【示例】UDP實現多線程客戶端

#coding=utf-8
from socket import *
from threading import Thread
udp_socket=socket(AF_INET,SOCK_DGRAM)
#綁定接收信息端口
udp_socket.bind(('127.0.0.1',8080))
#不停接收
def recv_data():while True:redata = udp_socket.recvfrom(1024)print(f'收到信息: {redata[0].decode("gbk")}, from {redata[1]}')
#不停發送
def send_data():while True:data=input('輸入信息:')addr=('127.0.0.1',8989)udp_socket.sendto(data.encode('gbk'),addr)
if __name__=='__main__':# 創建兩個線程t1=Thread(target=send_data)t2=Thread(target=recv_data)t2.start()t1.start()t1.join()t2.join()

TCP編程介紹

面向連接的Socket使用的協議是TCP協議。TCP的Socket名稱是 SOCK_STREAM 。創建套接字TCP套接字,可以調用 socket.socket() 。示例代碼如下:

tcpSocket=socket.socket(AF_INET,SOCK_STREAM)

?TCP編程的實現

在Python語言中創建Socket服務端程序,需要使用socket模塊中的 socket類。創建Socket服務器程序的步驟如下:

(1) 創建Socket對象。

(2) 綁定端口號。

(3) 監聽端口號。

(4) 等待客戶端Socket的連接。

(5) 讀取客戶端發送過來的數據。

(6) 向客戶端發送數據。

(7) 關閉客戶端Socket連接。

(8) 關閉服務端Socket連接。

?【示例】TCP服務器端接收數據

#coding=utf-8
from socket import *
server_socket = socket(AF_INET, SOCK_STREAM)
server_socket.bind(("", 8899))
server_socket.listen(5)
client_socket, client_info =
server_socket.accept()
#clientSocket 表示這個新的客戶端
#clientInfo 表示這個新的客戶端的ip以及port
recv_data = client_socket.recv(1024)
print(f"收到信息:{recv_data.decode('gbk')},來自:{client_info}")
client_socket.close()
server_socket.close()

【示例】TCP客戶端發送數據到服務端

#coding=utf-8
from socket import *
client_socket = socket(AF_INET, SOCK_STREAM)
client_socket.connect(("127.0.0.1", 8899))
#注意:
# 1. tcp客戶端已經鏈接好了服務器,所以在以后的數據發
送中,不需要填寫對方的ip和port----->打電話
# 2. udp在發送數據的時候,因為沒有之前的鏈接,所以需
要在每次的發送中,都要填寫接收方的ip和port----->寫信 
client_socket.send("haha".encode("gbk"))
client_socket.close()

TCP雙向持續通信

【示例】TCP:雙向通信Socket之服務器端

#coding=utf-8
'''
雙向通信Socket之服務器端讀取客戶端發送的數據,將內容輸出到控制臺將控制臺輸入的信息發送給客戶器端
'''
#導入socket模塊
from socket import *
#創建Socket對象
tcp_server_socket=socket(AF_INET,SOCK_STREAM)
#綁定端口
tcp_server_socket.bind(('', 8888))
#監聽客戶端的連接
tcp_server_socket.listen()
print("服務端已經啟動,等待客戶端連接!")
#接收客戶端連接
tcp_client_socket,
host=tcp_server_socket.accept()
print("一個客戶端建立連接成功!")
while True:#讀取客戶端的消息re_data=tcp_client_socket.recv(1024).decode('gbk')#將消息輸出到控制臺print('客戶端說:',re_data)if re_data=='end':break#獲取控制臺信息msg=input('>')tcp_client_socket.send(msg.encode('gbk'))
tcp_client_socket.close()
tcp_server_socket.close()

【示例】TCP:雙向通信Socket之客戶端

#coding=utf-8
'''
雙向通信Socket之客戶端將控制臺輸入的信息發送給服務器端讀取服務器端的數據,將內容輸出到控制臺
'''
#導入socket模塊
from socket import *
#創建客戶端Socket對象
tcp_client_socket=socket(AF_INET,SOCK_STREAM)
#連接服務器端
tcp_client_socket.connect(('127.0.0.1',8888))
while True:msg=input('>')#向服務器發送數據tcp_client_socket.send(msg.encode('gbk'))if msg=='end':break#接收服務器端數據re_data=tcp_client_socket.recv(1024)print('服務器端說:',re_data.decode('gbk'))
tcp_client_socket.close()

首先運行示例啟動服務器端程序,然后運行示例客戶端程序。執行結果如下圖所示:

?

?結合多線程實現TCP雙向傳送(自由聊天)

【示例】TCP服務端結合多線程實現自由收發信息

#coding=utf-8
'''
雙向通信Socket之服務器端讀取客戶端發送的數據,將內容輸出到控制臺將控制臺輸入的信息發送給客戶器端
'''
#導入socket模塊
from socket import *
from threading import Thread
def recv_data():while True:# 讀取客戶端的消息re_data =
tcp_client_socket.recv(1024).decode('gbk')# 將消息輸出到控制臺print(f'客戶端說:{re_data}')if re_data == 'end':break
def send_data():while True:# 獲取控制臺信息msg = input('>')tcp_client_socket.send(msg.encode('gbk'))
if __name__ == '__main__':# 創建Socket對象tcp_server_socket = socket(AF_INET,SOCK_STREAM)# 綁定端口tcp_server_socket.bind(('', 8888))# 監聽客戶端的連接tcp_server_socket.listen()print("服務端已經啟動,等待客戶端連接!")# 接收客戶端連接tcp_client_socket, host = tcp_server_socket.accept()print("一個客戶端建立連接成功!")t1 = Thread(target=recv_data)t2 = Thread(target=send_data)t1.start()t2.start()t1.join()t2.join()tcp_client_socket.close()tcp_server_socket.close()

【示例】TCP客戶端結合多線程實現自由收發信息

#coding=utf-8
'''
雙向通信Socket之客戶端將控制臺輸入的信息發送給服務器端讀取服務器端的數據,將內容輸出到控制臺
'''
#導入socket模塊
from socket import *
from threading import Thread
def recv_data():while True:# 接收服務器端數據re_data = tcp_client_socket.recv(1024)print(f'\n服務器端說: {re_data.decode("gbk")}')
def send_data():while True:msg = input('>')# 向服務器發送數據tcp_client_socket.send(msg.encode('gbk'))if msg == 'end':break
if __name__ == '__main__':# 創建客戶端Socket對象tcp_client_socket = socket(AF_INET,SOCK_STREAM)# 連接服務器端tcp_client_socket.connect(('127.0.0.1',8888))t1 = Thread(target=recv_data)t2 = Thread(target=send_data)t1.start()t2.start()t1.join()t2.join()tcp_client_socket.close()

關于http協議和服務器的授課順序說明

由于大家還沒有學習網頁內容,考慮到更好的和實戰結合。 所以,在講服務器編程時,詳細展開。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41720.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41720.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41720.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【c語言】通訊錄(動態版+文件+背景音樂)含源碼

開飯了,之前寫的通訊錄,是否會有人覺得申請1000人的空間是不是有點用不上呀,怎么才能做到要多少申請多少個呢??我們學完動態內存管理,和文件的相關操作,終于可以繼續完善我們的通訊錄了 船新版本…

機器學習基礎(三)

邏輯回歸 場景 垃圾郵件分類 預測腫瘤是良性還是惡性 預測某人的信用是否良好 正確率與召回率 正確率與召回率(Precision & Recall)是廣泛應用于信息檢索和統計學分類領域的兩個度量值,用來評價結果的質量。 一般來說,正確率就是檢索出來的條目有多少是正確的,召回率就…

salesforce創建定時任務時明明implements the Schedulable interface卻提示不是的解決方法

Apex類: global class TimesheetWeeklyJob implements Schedulable{global void execute( SchedulableContext SC ) {WeeklyTimesheetProcess.markSubmitted();WeeklyTimesheetProcess.createNewSheets();} }卻提示: Error: You must select an Apex cl…

數據結構:二叉樹的遞歸實現(C實現)

個人主頁 : 個人主頁 個人專欄 : 《數據結構》 《C語言》 文章目錄 前言一、樹的概念二、二叉樹二叉樹的概念二叉樹的性質 三、二叉樹鏈式結構實現二叉樹節點定義創建二叉樹節點遍歷二叉樹先序遍歷二叉樹(BinaryTreePrevOrder)中序遍歷二叉樹(BinaryTree…

Air780EG —— 合宙4G定位解決方案

定位模式: 外部單片機控制模式(常見于AT固件客戶): 開機 -> 搜星 -> 定位成功 -> 上報 -> 關機 780E自行控制模式(常見于二次開發客戶,AT用戶也可以使用): 開機 -> 搜星 -> 定位成功 -> 模塊休眠,關閉GP…

億發創新中醫藥信息化解決方案,自動化煎煮+調劑,打造智能中藥房

傳統中醫藥行業逐步復興,同時互聯網科技和人工智能等信息科技助力中醫藥行業逐步實現數字化轉型。利用互聯網、物聯網、大數據等科技,實現現代科學與傳統中醫藥的結合,提供智能配方顆粒調配系統、中藥自動化調劑系統、中藥煎配智能管理系統、…

【從零學習python 】40.python魔法方法(一)

文章目錄 魔法方法1. __init__ 方法2. __del__ 方法3. __str__ 方法4. __repr__ 方法5. __call__ 方法進階案例 魔法方法 Python 里有一種方法,叫做魔法方法。Python 的類里提供的,兩個下劃線開始,兩個下劃線結束的方法,就是魔法…

如何切換goland之中的版本號(升級go 到1.20)

go 安裝/版本切換_go 切換版本_云滿筆記的博客-CSDN博客 用brew就行: echo export PATH"/opt/homebrew/opt/go1.20/bin:$PATH" >> ~/.zshrc

[國產MCU]-BL602開發實例-OLED-SSD1306驅動與U8g2移植

OLED-SSD1306驅動與U8g2移植 文章目錄 OLED-SSD1306驅動與U8g2移植1、OLED介紹2、SSD1306介紹2、U8g2介紹3、U8g2移植3.1 定義U8g2圖形庫的移植函數3.2 移植函數實現3.3 移植函數調用4、驅動測試本文將詳細介紹如何在BL602中移植U8g2圖形庫,并通過U8g2庫驅動OLED SSD1306顯示屏…

Linux6.40 Kubernetes 配置資源管理

文章目錄 計算機系統5G云計算第三章 LINUX Kubernetes 配置資源管理一、Secret1.Secret 四種類型1)kubernetes.io/service-account-token2)Opaque3)kubernetes.io/dockerconfigjson4)kubernetes.io/tls 2.Pod 需要先引用才能使用某…

React入門 jsx學習筆記

一、JSX介紹 概念:JSX是 JavaScript XML(HTML)的縮寫,表示在 JS 代碼中書寫 HTML 結構 作用:在React中創建HTML結構(頁面UI結構) 優勢: 采用類似于HTML的語法,降低學…

因果推斷(四)斷點回歸(RD)

因果推斷(四)斷點回歸(RD) 在傳統的因果推斷方法中,有一種方法可以控制觀察到的混雜因素和未觀察到的混雜因素,這就是斷點回歸,因為它只需要觀察干預兩側的數據,是否存在明顯的斷點…

【C++入門到精通】C++入門 —— list (STL)

閱讀導航 前言一、list簡介1.概念2.特點 二、list的使用1.list的構造2.常見的操作?std::list類型的增、刪、查、改 三、list與vector的對比溫馨提示 前言 文章綁定了VS平臺下std::list的源碼,大家可以下載了解一下😍 前面我們講了C語言的基礎知識&…

C語言實例_獲取文件MD5值

一、MD5介紹 MD5(Message Digest Algorithm 5)是一種常用的哈希函數算法。將任意長度的數據作為輸入,并生成一個唯一的、固定長度(通常是128位)的哈希值,稱為MD5值。MD5算法以其高度可靠性和廣泛應用而聞名…

全球磁強計市場價值約為16.2億美元,預測期內將以超過5.21%的增長率增長

磁強計是一種用于測量磁場強度和方向的儀器。它可以檢測和測量地球磁場、物體的磁性、地下礦藏、磁性材料等。磁強計在地球科學、物理學、地質學、勘探、礦業等領域具有廣泛的應用。 根據阿譜爾(APO)的統計及預測,2022年全球磁強計市場價值約…

跳跳!(c++題解)

題目描述 你是一只小跳蛙,你特別擅長在各種地方跳來跳去。 這一天,你和朋友小 F 一起出去玩耍的時候,遇到了一堆高矮不同的石頭,其中第 ii 塊的石頭高度為 hi?,地面的高度是 h0?0。你估計著,從第 ii 塊…

ts與vue

ts與Vue 如果你已經學習了typeScript,但不知道如何在vue項目中使用,那么這篇文章將會很適合你。參考千峰教育 kerwin視頻 1.會自動推導,隱士推導。提示 類型系統。 獨立模塊。 isolatedModules選項:是否配置為獨立的模塊。 減少報錯 let …

dispatcherServlet在tomcat啟動時如何被加載(1)

目錄 在springboot工程中, 如何添加一個servlet呢? 方法1 : 使用WebServlet注解 方法2 : 使用ServletRegistrationBean進行注冊 springmvc 采用的就是方式2和springboot集成的, 看一下源碼 springboot 字段裝配里面有這個類, 看一下源碼 90行, 創建了一個DispatcherServlet對象…

深入探究Socks5代理與IP代理在網絡安全與爬蟲中的應用

1. Socks5代理:打開網絡隧道的多功能工具 Socks5代理是一種流行的代理協議,它在傳輸層為數據包提供了隧道。相較于之前的版本,Socks5不僅支持TCP連接,還可以處理UDP流量,使其在需要實時數據傳輸的應用中表現出色。在網…

Zabbix配置通用的TCP/IP:port監控項

我們經常的用接口,比如說FTP、HTTP、DNS、數據庫接口,都可以用IP:PORT方式探測其是否存活,那么我們去繁就簡,就簡單監控一下IP:PORT吧! 1、新建主機: 填入主機名稱、群組、Agent就是127.0.0.1…