詳解python UDP 編程
前面我們講了 TCP 編程,我們知道 TCP 可以建立可靠連接,并且通信雙方都可以以流的形式發(fā)送數(shù)據(jù)。本文我們再來介紹另一個常用的協(xié)議–UDP。相對TCP,UDP則是面向無連接的協(xié)議。
UDP 協(xié)議
我們來看 UDP 的定義:
UDP 協(xié)議(User Datagram Protocol),中文名是用戶數(shù)據(jù)報協(xié)議,是 OSI(Open System Interconnection,開放式系統(tǒng)互聯(lián)) 參考模型中一種無連接的傳輸層協(xié)議,提供面向事務的簡單不可靠信息傳送服務。
從這個定義中,我們可以總結(jié)出 UDP 的幾個特點以及其與 TCP 的區(qū)別:
- UDP 是用戶數(shù)據(jù)報協(xié)議,傳輸模式是數(shù)據(jù)報,而 TCP 是基于字節(jié)流的傳輸協(xié)議。
- UDP 是無連接的協(xié)議,每個數(shù)據(jù)報都是一個獨立的信息,包括完整的源地址或目的地址,它在網(wǎng)絡上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內(nèi)容的正確性都是不能被保證的。
- UDP 是簡單不可靠的協(xié)議,它不提供可靠性,只是把數(shù)據(jù)包發(fā)送出去,并不保證能夠到達目的地。由于它不需要在客戶端和服務端之間建立連接,也沒有超時重發(fā)機制,所以傳輸速度很快。
從以上特點,我們可以看到 UDP 適合應用在每次傳輸數(shù)據(jù)量小、對數(shù)據(jù)完整性要求不高、對傳輸速度要求高的領(lǐng)域。這里面最典型的就是即時通信的場景,微信是一個很常見的例子。相信大家在使用微信的時候都遇到過先發(fā)的消息后收到,或者有些發(fā)送的消息對方?jīng)]有收到的情況吧,這就是 UDP 協(xié)議典型的特點,不保證傳輸數(shù)據(jù)的完整性和順序性。除此之外, UDP 還應用在在線視頻、網(wǎng)絡電話等場景。
UDP 傳輸過程
我們在講 TCP 的時候,我們說 TCP 客戶端和服務端必須先連接才可以傳輸數(shù)據(jù):客戶端先請求連接服務器,服務器接受連接請求,然后雙方才可以通信。在 UDP 協(xié)議里,客戶端只需要知道服務器的地址和端口號,就可以直接發(fā)送數(shù)據(jù)了。
我們來看下 UDP 傳輸?shù)牧鞒虉D:

UDP服務器的建立可以歸納這幾步:
- 創(chuàng)建 socket(套接字)
- 綁定 socket 的 IP 地址和端口號
- 接收客戶端數(shù)據(jù)
- 關(guān)閉連接
udp客戶端的創(chuàng)建可總結(jié)為這幾步:
- 創(chuàng)建 socket(套接字)
- 向服務器發(fā)送數(shù)據(jù)
- 關(guān)閉連接
這里需要注意的是 UDP 客戶端連接到服務器的 IP 和端口號必須是 UDP 服務器的 IP 和監(jiān)聽的端口號,服務器服務器只需要綁定 IP 和端口號,就可以時刻準備接收客戶端發(fā)送的數(shù)據(jù),此時服務器處于阻塞狀態(tài),直到接收到數(shù)據(jù)為止。
UDP 客戶端
創(chuàng)建 socket,可以這樣做:
# 導入socket庫 import socket # 創(chuàng)建一個socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
創(chuàng)建 socket 時,第一個參數(shù) socket.AF_INET 表示指定使用 IPv4 協(xié)議,如果要使用 IPv6 協(xié)議,就指定為 socket.AF_INET6。SOCK_DGRAM 指定基于 UDP 的數(shù)據(jù)報式 Socket 通信。
創(chuàng)建了 socket 之后,我們就可以向目標地址發(fā)送數(shù)據(jù)報了:
# 發(fā)送數(shù)據(jù)
s.sendto(b'Hello Server', ('127.0.0.1', 6000))
第一個參數(shù)是需要發(fā)送的數(shù)據(jù)報內(nèi)容,第二個參數(shù)是 IP 地址和端口號的二元組。
如果是接收數(shù)據(jù)的話,我們可以這樣寫:
# 接收數(shù)據(jù)
data, addr = s.recv(1024)
# 解碼接收到的數(shù)據(jù)
data = data.decode('utf-8')
接收信息的時候,第一個 data 表示接收到的數(shù)據(jù), addr 是對方的 IP 地址和端口號的二元組。
想要關(guān)閉 socket,直接調(diào)用 close() 方法即可:
# 關(guān)閉 socket socket.close()
UDP 服務器
相比于客戶端,服務器端只是多了一個步驟,在創(chuàng)建 socket 之后,需要綁定一個 IP 地址和端口號,以便接收客戶端隨時可能發(fā)送過來的數(shù)據(jù)。綁定的方法為:
# 綁定 IP 和端口
s.bind(('127.0.0.1', 6000))
UDP 簡單實例
我們通過一個簡單的實例來體會下 UDP 的客戶端和服務器的通信流程。
服務器代碼為:
import socket
# 創(chuàng)建 socket
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 綁定 IP 和端口號
sk.bind(('127.0.0.1', 6000))
while True:
# 接收數(shù)據(jù)報
msg, addr = sk.recvfrom(1024)
# 打印
print('來自[%s:%s]的消息: %s' % (addr[0], addr[1], msg.decode('utf-8')))
# 等待輸入
inp = input('>>>')
# 發(fā)送數(shù)據(jù)報
sk.sendto(inp.encode('utf-8'), addr)
# 關(guān)閉 socket
sk.close()
這里,我們先創(chuàng)建 socket,然后綁定本機的6000端口,然后等待接收客戶端發(fā)送的數(shù)據(jù)報,接收到數(shù)據(jù)后將數(shù)據(jù)內(nèi)容打印在控制臺。然后可以在控制臺輸入回復內(nèi)容,發(fā)送給客戶端。
客戶端代碼:
import socket
# 創(chuàng)建 socket
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = ('127.0.0.1', 6000)
while True:
# 等待輸入
msg = input('>>>')
# 發(fā)送數(shù)據(jù)報
sk.sendto(msg.encode('utf-8'), addr)
# 接收數(shù)據(jù)報
msg_recv, addr = sk.recvfrom(1024)
# 打印
print(msg_recv.decode('utf-8'))
# 關(guān)閉 socket
sk.close()
在客戶端代碼中,我們就只是創(chuàng)建 socket,然后在控制臺輸入需要向服務器發(fā)送的內(nèi)容,通過 sentto() 方法發(fā)送給服務器,然后接收服務器返回的內(nèi)容,將接收的內(nèi)容打印到控制臺。
分別運行客戶端和服務器代碼,然后我們在客戶端的控制臺輸入 “hello server”,我們可以看到服務器的控制臺打印了客戶端發(fā)送的內(nèi)容,然后我們在服務器控制臺輸入 “hello client”,同樣在客戶端控制臺可以看你到內(nèi)容。
下面是客戶端的控制臺內(nèi)容:
>>>hello server hello client >>>
下面是服務器的控制臺內(nèi)容:
來自[127.0.0.1:61207]的消息: hello server >>>hello client
這個實例其實就是一個簡單的聊天模型,客戶端和服務器就像兩個人一樣可以發(fā)送和接收對方的信息。
那么多人群聊怎么實現(xiàn)呢?簡單來說,我們需要設(shè)置一臺中心服務器,我們每個人發(fā)送的內(nèi)容都先發(fā)送到中心服務器,然后中心服務器再轉(zhuǎn)發(fā)到每個群聊的人。
總結(jié)
本文為大家介紹了 UDP 編程的基本原理以及通過 Python 實現(xiàn)一個最簡單的聊天程序來模擬 UDP 通信的過程。通過本文的學習,我們需要對 UDP 協(xié)議有基本的認識,以及對 UDP 的通信過程比較熟悉。
以上就是詳解python UDP 編程的詳細內(nèi)容,更多關(guān)于python UDP 編程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
django數(shù)據(jù)模型中null和blank的區(qū)別說明
這篇文章主要介紹了django數(shù)據(jù)模型中null和blank的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Python爬取用戶觀影數(shù)據(jù)并分析用戶與電影之間的隱藏信息!
看電影前很多人都喜歡去 『豆瓣』 看影評,所以我爬取44130條 『豆瓣』 的用戶觀影數(shù)據(jù),分析用戶之間的關(guān)系,電影之間的聯(lián)系,以及用戶和電影之間的隱藏關(guān)系,需要的朋友可以參考下2021-06-06
python3 requests中使用ip代理池隨機生成ip的實例
今天小編就為大家分享一篇python3 requests中使用ip代理池隨機生成ip的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05

