詳解python UDP 程式設計
前面我們講了 TCP 程式設計,我們知道 TCP 可以建立可靠連線,並且通訊雙方都可以以流的形式傳送資料。本文我們再來介紹另一個常用的協議–UDP。相對TCP,UDP則是面向無連線的協議。
UDP 協議
我們來看 UDP 的定義:
UDP 協議(User Datagram Protocol),中文名是使用者資料報協議,是 OSI(Open System Interconnection,開放式系統互聯) 參考模型中一種無連線的傳輸層協議,提供面向事務的簡單不可靠資訊傳送服務。
從這個定義中,我們可以總結出 UDP 的幾個特點以及其與 TCP 的區別:
- UDP 是使用者資料報協議,傳輸模式是資料報,而 TCP 是基於位元組流的傳輸協議。
- UDP 是無連線的協議,每個資料報都是一個獨立的資訊,包括完整的源地址或目的地址,它在網路上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。
- UDP 是簡單不可靠的協議,它不提供可靠性,只是把資料包傳送出去,並不保證能夠到達目的地。由於它不需要在客戶端和服務端之間建立連線,也沒有超時重發機制,所以傳輸速度很快。
從以上特點,我們可以看到 UDP 適合應用在每次傳輸資料量小、對資料完整性要求不高、對傳輸速度要求高的領域。這裡面最典型的就是即時通訊的場景,微信是一個很常見的例子。相信大家在使用微信的時候都遇到過先發的訊息後收到,或者有些傳送的訊息對方沒有收到的情況吧,這就是 UDP 協議典型的特點,不保證傳輸資料的完整性和順序性。除此之外, UDP 還應用在線上視訊、網路電話等場景。
UDP 傳輸過程
我們在講 TCP 的時候,我們說 TCP 客戶端和服務端必須先連線才可以傳輸資料:客戶端先請求連線伺服器,伺服器接受連線請求,然後雙方才可以通訊。在 UDP 協議裡,客戶端只需要知道伺服器的地址和埠號,就可以直接傳送資料了。
我們來看下 UDP 傳輸的流程圖:
UDP伺服器的建立可以歸納這幾步:
- 建立 socket(套接字)
- 繫結 socket 的 IP 地址和埠號
- 接收客戶端資料
- 關閉連線
udp客戶端的建立可總結為這幾步:
- 建立 socket(套接字)
- 向伺服器傳送資料
- 關閉連線
這裡需要注意的是 UDP 客戶端連線到伺服器的 IP 和埠號必須是 UDP 伺服器的 IP 和監聽的埠號,伺服器伺服器只需要繫結 IP 和埠號,就可以時刻準備接收客戶端傳送的資料,此時伺服器處於阻塞狀態,直到接收到資料為止。
UDP 客戶端
建立 socket,可以這樣做:
# 匯入socket庫 import socket # 建立一個socket s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
建立 socket 時,第一個引數 socket.AF_INET 表示指定使用 IPv4 協議,如果要使用 IPv6 協議,就指定為 socket.AF_INET6。SOCK_DGRAM 指定基於 UDP 的資料報式 Socket 通訊。
建立了 socket 之後,我們就可以向目標地址傳送資料報了:
# 傳送資料 s.sendto(b'Hello Server',('127.0.0.1',6000))
第一個引數是需要傳送的資料報內容,第二個引數是 IP 地址和埠號的二元組。
如果是接收資料的話,我們可以這樣寫:
# 接收資料 data,addr = s.recv(1024) # 解碼接收到的資料 data = data.decode('utf-8')
接收資訊的時候,第一個 data 表示接收到的資料, addr 是對方的 IP 地址和埠號的二元組。
想要關閉 socket,直接呼叫 close() 方法即可:
# 關閉 socket socket.close()
UDP 伺服器
相比於客戶端,伺服器端只是多了一個步驟,在建立 socket 之後,需要繫結一個 IP 地址和埠號,以便接收客戶端隨時可能傳送過來的資料。繫結的方法為:
# 繫結 IP 和埠 s.bind(('127.0.0.1',6000))
UDP 簡單例項
我們通過一個簡單的例項來體會下 UDP 的客戶端和伺服器的通訊流程。
伺服器程式碼為:
import socket # 建立 socket sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 繫結 IP 和埠號 sk.bind(('127.0.0.1',6000)) while True: # 接收資料報 msg,addr = sk.recvfrom(1024) # 列印 print('來自[%s:%s]的訊息: %s' % (addr[0],addr[1],msg.decode('utf-8'))) # 等待輸入 inp = input('>>>') # 傳送資料報 sk.sendto(inp.encode('utf-8'),addr) # 關閉 socket sk.close()
這裡,我們先建立 socket,然後繫結本機的6000埠,然後等待接收客戶端傳送的資料報,接收到資料後將資料內容列印在控制檯。然後可以在控制檯輸入回覆內容,傳送給客戶端。
客戶端程式碼:
import socket # 建立 socket sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) addr = ('127.0.0.1',6000) while True: # 等待輸入 msg = input('>>>') # 傳送資料報 sk.sendto(msg.encode('utf-8'),addr) # 接收資料報 msg_recv,addr = sk.recvfrom(1024) # 列印 print(msg_recv.decode('utf-8')) # 關閉 socket sk.close()
在客戶端程式碼中,我們就只是建立 socket,然後在控制檯輸入需要向伺服器傳送的內容,通過 sentto() 方法傳送給伺服器,然後接收伺服器返回的內容,將接收的內容列印到控制檯。
分別執行客戶端和伺服器程式碼,然後我們在客戶端的控制檯輸入 “hello server”,我們可以看到伺服器的控制檯列印了客戶端傳送的內容,然後我們在伺服器控制檯輸入 “hello client”,同樣在客戶端控制檯可以看你到內容。
下面是客戶端的控制檯內容:
>>>hello server hello client >>>
下面是伺服器的控制檯內容:
來自[127.0.0.1:61207]的訊息: hello server >>>hello client
這個例項其實就是一個簡單的聊天模型,客戶端和伺服器就像兩個人一樣可以傳送和接收對方的資訊。
那麼多人群聊怎麼實現呢?簡單來說,我們需要設定一臺中心伺服器,我們每個人傳送的內容都先發送到中心伺服器,然後中心伺服器再轉發到每個群聊的人。
總結
本文為大家介紹了 UDP 程式設計的基本原理以及通過 Python 實現一個最簡單的聊天程式來模擬 UDP 通訊的過程。通過本文的學習,我們需要對 UDP 協議有基本的認識,以及對 UDP 的通訊過程比較熟悉。
以上就是詳解python UDP 程式設計的詳細內容,更多關於python UDP 程式設計的資料請關注我們其它相關文章!