用戶數據報協議,是一個無鏈接的面向數據報的運輸層協議。python
UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發出去,可是並不能保證他們能到達目的地。服務器
因爲UDP在傳輸數據報前不用在客戶和服務器之間創建一個鏈接,且沒有超時重發等機制,故而傳輸速度很快。網絡
UDP是一種面向無鏈接的協議,每一個數據報都是一個獨立的信息,包括完整的源地址或目的地址,它在網絡上以任何可能的路徑傳往目的地,所以可否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。socket
UDP能夠理解爲寫信,TCP能夠理解爲打電話。tcp
UDP在互聯網中的丟包率幾乎爲0,在互聯網中(美國到中國),丟包率也很低,可是始終仍是存在丟包的可能spa
UDP是面向無鏈接的通信協議code
UDP數據包括目的端口號和源端口號信息視頻
通信不須要創建鏈接,因此能夠實現廣播發送server
UDP傳輸數據有大小限制,每一個被傳輸的數據報必須限定在64KB以內blog
UDP是一個不可靠的協議,發送方發送的數據報並不必定以相同的次序到達接收方
多點通訊和實時性要求高的場景
UDP是面向消息的協議,通訊時不須要創建鏈接,數據的傳輸天然是不可靠的,UDP通常用於多點通訊和實時的數據業務員,如:
語音廣播、視頻、QQ、TFTP(簡單文件傳送)、SNMP(簡單網絡管理協議)、RIP(路由信息協議,如報告股票市場,航空信息)、DNS(域名解釋)
注重速度流暢的場景
UDP操做簡單,並且僅須要較少的監護,所以一般用於局域網高可靠性的分散系統中的client/server應用程序。如:視頻會議系統,並不要求音頻視頻數據絕對的正確,只要保證連貫性就能夠了,這種狀況下顯然使用UDP會更合理。
流程
建立一個UDP的程序的流程很簡單,以下:
一、建立客戶端套接字
二、發送/接收數據
三、關閉套接字
原理
通常狀況下,在一臺電腦上運行的網絡程序不少,而各自用的端口號不少狀況下是不知道的,爲了不與其餘的網絡程序佔用同一個端口號,每每在代碼中,udp的端口號是不綁定的。
對於發送方(客戶端程序),端口號隨機分配問題不大,可是對於接收方(服務器)來講,最好綁定一個固定的端口,那麼別人往服務器發送數據的時候,只須要往約定好的端口發送數據便可。想一想若是服務器的端口號是任意的,那麼每次往服務器發送數據的時候還須要肯定端口號,可是服務器的端口號是隨機的,如何肯定?!
若是是一個服務器端的程序的話,就須要綁定端口號了。想一想若是報警電話天天都在變,想必世界就會亂了,因此通常服務性的程序,每每須要一個固定的端口號,這就是所謂的端口綁定。
報警電話爲110,只能定死,而撥打110的號碼,能夠是手機,能夠是別人的手機,能夠是座機,能夠是公用電話等等。可見綁定端口,通常是接收方(服務器)才須要綁定端口,而發送方是不須要綁定端口。
聽:接收
說:發送
單工:如收音機,只能聽,不能說話
半雙工:如對講機,當某我的在說話時,你不能說話,當沒人說話時,你可說話
全雙工:如電話,能夠同時說話。socket就是全雙工的,在接收數據的同時也能夠發送數據
# coding:utf-8 import socket import config def main(): # 建立udp的套接字 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 重用ip和port,防止報錯 sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 綁定ip和port sk.bind((config.host, config.port)) if config.connected: # 要創建鏈接 nsk, addr = sk.accept() # 經過新的socket去接收數據 data = nsk.recv(1024) else: # 不用創建鏈接,只有udp才能這麼寫,tcp是必須先創建鏈接的 data, addr = sk.recvfrom(1024) print(data) if __name__ == '__main__': main()
# coding:utf-8 import socket import config def main(): # 建立udp的套接字 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 地址 addr = (config.host, config.port) # 要發送的內容 send_data = b"hello" if config.connected: # 要創建鏈接 sk.connect(addr) sk.send(send_data) else: # 不用創建鏈接 sk.sendto(send_data, addr) if __name__ == '__main__': main()