UDP協議: 1、python中基於udp協議的客戶端與服務端通信簡單過程實現 2、udp協議的一些特點(與tcp協議的比較) 3、利用socketserver模塊實現udp傳輸協議的併發通信 一、UDP協議:OSI七層協議中的傳輸協議的一種(另外一種tcp協議),他們都是一種埠協議 與TCP協議 ...
UDP協議:
1、python中基於udp協議的客戶端與服務端通信簡單過程實現
2、udp協議的一些特點(與tcp協議的比較)
3、利用socketserver模塊實現udp傳輸協議的併發通信
-------------------------------------------------------------------------------------------------------------------------------------
一、UDP協議:OSI七層協議中的傳輸協議的一種(另外一種tcp協議),他們都是一種埠協議
- 與TCP協議不同的是,UDP協議在傳輸時候無需雙方建立雙向連接,只需要知道對方的IP和PORT(埠)就可以
而且UDP協議傳輸具有不安全行,或者說是即時性,給對方發送信息時候,只管發,至於他收不收得到都不會去考慮,
不管是服務端還是客戶端都一樣。
- UDP叫數據報協議,意味著發消息都帶有數據報頭,UDP的server不需要進行監聽也無需建立連接,在啟動服務之後只能被動的等待客戶端發消息過來,客戶端發消息的時候,要帶上服務端的地址,服務端在回消息的時候,也要帶上客戶端的地址
下麵來簡單實現基於UDP協議的客戶端、服務端通信
# 服務端: import socket # udp傳輸的服務端無需半連接池,因為通信無需建立雙向連接通道,無需三次握手四次揮手,只要知道對方ip和port就行 server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) # 通信迴圈 while True: data, client_addr = server.recvfrom(1024) # 這裡接收用recvfrom print('收到客戶端發來的udp消息%s' % data.decode('utf-8')) server.sendto(data.upper(), client_addr) # 這裡發送用sendto # 客戶端: import socket # 無需connect服務端,因為發送時候跟上服務端ip和port就行 client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) while True: msg = 'hello' client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) data, server_addr = client.recvfrom(1024) print(data.decode('utf-8'))
二、UDP協議的一些特點
總結幾個UDP協議的特點:
- 客戶端允許發空
- 不會粘包
- 服務端不存在的時候,客戶端照發無誤,不會報錯(*-*)
- 可以實現簡單的併發效果
# 驗證UDP是否有粘包問題: from socket import * server = socket(AF_INET, SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) while True: data1, addr = server.recvfrom(1024) data2, addr = server.recvfrom(1024) data3, addr = server.recvfrom(1024) data4, addr = server.recvfrom(1024) data5, addr = server.recvfrom(1024) print(data1) print(data2) print(data3) print(data4) print(data5) from socket import * client = socket(AF_INET, SOCK_DGRAM) while True: client.sendto(b'Hello1', ('127.0.0.1', 8080)) client.sendto(b'Hello2', ('127.0.0.1', 8080)) client.sendto(b'Hello3', ('127.0.0.1', 8080)) client.sendto(b'Hello4', ('127.0.0.1', 8080)) client.sendto(b'Hello5', ('127.0.0.1', 8080)) # 列印的每條數據都是獨立的,沒有2條數據在一起的情況 UDP不存在粘包問題,是由於UDP發送的時候,沒有經過Nagle演算法的優化,不會將多個小包合併一次發送出去。另外,在UDP協議的接收端,採用了鏈式結構來記錄每一個到達的UDP包,這樣接收端應用程式一次recv只能從socket接收緩衝區中讀出一個數據包。也就是說,發送端send了幾次,接收端必須recv幾次(無論recv時指定了多大的緩衝區)。
三、利用socketserver模塊實現udp協議的併發通信
## 服務端: import socketserver from threading import currentThread # 這裡導入當前線程方法,得到當前線程名稱 class MyUdpHandler(socketserver.BaseRequestHandler): def handle(self): # 這裡和tcp利用socketserver模塊併發的服務端不一樣,tcp服務端是直接data = self.request.recv(1024) data, sock = self.request # 這裡多了一個sock,這個sock用於發送,同時self對象本身可以得到client_address msg = '%s [%s]' % (currentThread().name, data.upper().decode('utf-8')) sock.sendto(msg.encode('utf-8'), self.client_address) if __name__ == '__main__': server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpHandler) server.serve_forever() ## 客戶端 from threading import Thread,currentThread import time from socket import * def task(): client = socket(AF_INET,SOCK_DGRAM) addr = ('127.0.0.1', 8080) n = 0 while n < 10: # 模擬讓每個客戶端與服務端通信迴圈10次。 msg = '%s [%s]' % (currentThread().name, n) client.sendto(msg.encode('utf-8'), addr) data, addr0 = client.recvfrom(1024) print(data.decode('utf-8')) n += 1 if __name__ == '__main__': for i in range(50): # 開啟50個客戶端線程去連接服務端,模擬併發 t = Thread(target=task) t.start()