鄙人學習筆記
UDP套接字編程
服務端流程
- 創建數據報套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
- 綁定地址
sockfd.bind(addr)
備註:作爲服務端,必然要綁定地址的。
- 消息收發
data,addr = sockfd.recvfrom(buffersize)
功能: 接收UDP消息
參數: 每次最多接收多少字節
返回值:
data 接收到的內容
addr 消息發送方地址
n = sockfd.sendto(data,addr)
功能: 發送UDP消息
參數:
data 發送的內容 bytes格式
addr 目標地址
返回值:發送的字節數
備註:由於UDP沒有創建連接,所以沒有一個專門的連接套接字對象(一發送就知道發送給誰),所以我們需要指明目標地址。
備註:UDP不需要創建連接。
- 關閉套接字
sockfd.close()
舉個例子
代碼:
from socket import *
#創建數據報套接字
sockfd = socket(AF_INET, SOCK_DGRAM)
#綁定地址
server_addr = ('127.0.0.1',8888)
sockfd.bind(server_addr)
#收發消息
while True:
data,addr = sockfd.recvfrom(1024)
print("收到的消息:",data.decode())
sockfd.sendto(b"Thanks",addr)
#關閉套接字
sockfd.close()
客戶端流程
- 創建數據報套接字
- 收發消息
- 關閉套接字
備註:依然要注意,客戶端與服務端的收發順序。若服務端先收後發,則客戶端先發後收。
舉個例子
服務端代碼:
客戶端代碼:
運行服務端:
運行客戶端,併發送消息:
查看服務端:
備註:由於是UDP協議,所以相當”自由”,可以同時接收多個客戶端發來的消息。在這裏就不演示了。
這裏,我們再更改一下服務端的recvfrom的參數,來控制一下每次最多能接收的字節數(客戶端代碼不變)。
服務端代碼:
用客戶端發送hello world:
客戶端接收到服務端的消息:
服務端輸出:
得到5個字節。
我們再用客戶端發送nihao:
服務端輸出:
咦?這是咋回事?咋和TCP的不太一樣?
…好吧,第一次發送的【hello world】的後面的【 world】丟失了。這是提供不可靠傳輸服務的體現。但這個是合理的,比如,客戶端A和客戶端B都向服務端send()消息,UDP協議的不可靠傳輸雖然可能會丟失消息,但不會使客戶端A發送過來的消息,顯示在客戶端B發送的消息裏面。這樣,寧願丟失消息,也不能導致混亂。
所以,UDP套接字傳輸中,如果一次接收消息接收不完(超過最多能接收的字節數),則會把剩下的消息(超過指定字節數的部分)丟棄。
同時,UDP數據傳輸是不存在粘包的問題,因爲它存在消息邊界。就像我們之前形容的那樣,TCP傳輸是水流,UDP傳輸是水瓶。UDP傳輸,是一個一個”數據報”傳輸的,它的消息之間是存在邊界的。
TCP套接字和UDP套接字編程區別
①流式套接字是以字節流方式傳輸數據;數據報套接字以數據報形式傳輸
②TCP套接字會有粘包;UDP套接字有消息邊界,不會粘包
③TCP套接字保證消息的完整性;UDP套接字則不能
④TCP套接字依賴listen、accept建立連接才能收發消息;UDP套接字則不需要
⑤TCP套接字使用send、recv收發消息;UDP套接字使用sendto、recvfrom