TCP | UDP | |
---|---|---|
鏈接性 | 面向鏈接 | 面向無鏈接 |
傳輸可靠性 | 可靠 | 不可靠 |
傳輸模式 | 流 | 數據報 |
應用場景 | 傳輸大量的數據 | 少許數據 |
速度 | 慢 | 快 |
TCP:python
TCP 的可靠體如今傳輸數據以前,會有三次握手來創建鏈接。在數據傳完後,還會斷開鏈接用來節約系統資源。在數據傳遞時,有確認機制、重傳機制、擁塞控制機制以保證傳輸的可靠性,但這些機制都會消耗大量的時間和系統資源,每一個鏈接都會佔用系統的 CPU、內存等硬件資源,因此也致使 TCP 容易被人利用,好比 DDOS、CC 等攻擊。編程
通常用於文件傳輸、收發郵件或遠程登陸等對數據準確性要求高的場景。segmentfault
UDP:服務器
UDP 沒有 TCP 那些可靠的機制,因此在數據傳遞時,若是網絡質量很差,就會很容易丟包。但 UDP 也是沒法避免攻擊的,好比:UDP Flood 攻擊。網絡
通常用於即時通信、在線視頻、網絡電話等對傳輸效率要求高,但對準確性要求相對低的場景。socket
- 面向有鏈接型
發送數據以前,須要在收發主機之間創建一條通訊線路,在通訊傳輸先後,專門進行創建和斷開鏈接的處理,若是與對端之間沒法通訊,可避免發送無謂的數據。函數
- 面向無鏈接型
這種類型不要求創建和斷開鏈接,發送端可任什麼時候候發送數據,接收端也不知道本身什麼時候從哪裏接受數據,這種狀況下,接收端須要時常確認是否收到數據,彼此也不須要確認對方是否存在。編碼
關於 TCP 網絡編程的實現請參考個人另外一篇博文 Socket 通訊原理spa
面向無鏈接的 UDP 時序圖code
建立 Socket
sock = socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
family -> 地址族
type -> Socket 對象的類型
建立 TCP Socket:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
建立 UDP Socket:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
UDP 通訊
sock.recvfrom(bufsize[, flags])
接受 UDP 套接字的數據,與 recv() 相似,但返回值是 tuple(data, address)
。其中 data 是包含接受數據的字符串,address 是發送數據的 Socket 地址
注意協議接收到的數據可能大於 buf 的長度,因此在這種狀況下要調用幾回 recv 函數才能把 Socket 接收緩衝區中的數據 copy 完。recv 函數僅僅是 copy 數據,真正接收數據是由協議來完成的。
sock.sendto(bytes, address)
發送 UDP 數據,將數據發送到 Socket,address 形式爲 tuple(ipaddr, port)
,指定遠程地址發送,返回值是發送的字節數
Python 2.x 發送的報文是 str 類型,Python 3.x 發送的報文是 bytes 類型,在發送前要記得編碼。
import socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) address = ('127.0.0.1', 8020) while True: msg = input('Wanna send: ') if not msg: break sock.sendto(bytes(msg, 'utf-8'), address) # Return the number of bytes sent data, addr = sock.recvfrom(1024) data = data.decode('utf-8') print('Response:', data) sock.close()
import socket import time sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('127.0.0.1', 8020)) print('waiting for message...') while True: data, addr = sock.recvfrom(1024) data = data.decode('utf-8') print('Got message from', addr) print('Received message:', data) sock.sendto(bytes('[%s] %s' % (time.ctime(), data), 'utf-8'), addr) sock.close()