Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀
UDP概述
UDP 是User Datagram Protocol的簡(jiǎn)稱, 中文名是用戶數(shù)據(jù)報(bào)協(xié)議,是OSI(Open System Interconnection,開(kāi)放式系統(tǒng)互聯(lián)) 參考模型中一種無(wú)連接的傳輸層協(xié)議,提供面向事務(wù)的簡(jiǎn)單不可靠信息傳送服務(wù),IETF RFC 768是UDP的正式規(guī)范。UDP在IP報(bào)文的協(xié)議號(hào)是17。
UDP協(xié)議全稱是用戶數(shù)據(jù)報(bào)協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無(wú)連接的協(xié)議。在OSI模型中,在第四層——傳輸層,處于IP協(xié)議的上一層。UDP有不提供數(shù)據(jù)包分組、組裝和不能對(duì)數(shù)據(jù)包進(jìn)行排序的缺點(diǎn),也就是說(shuō),當(dāng)報(bào)文發(fā)送之后,是無(wú)法得知其是否安全完整到達(dá)的。UDP用來(lái)支持那些需要在計(jì)算機(jī)之間傳輸數(shù)據(jù)的網(wǎng)絡(luò)應(yīng)用。包括網(wǎng)絡(luò)視頻會(huì)議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都需要使用UDP協(xié)議。UDP協(xié)議從問(wèn)世至今已經(jīng)被使用了很多年,雖然其最初的光彩已經(jīng)被一些類似協(xié)議所掩蓋,但是即使是在今天UDP仍然不失為一項(xiàng)非常實(shí)用和可行的網(wǎng)絡(luò)傳輸層協(xié)議。
UDP主要特點(diǎn)
UDP是一個(gè)無(wú)連接協(xié)議,傳輸數(shù)據(jù)之前源端和終端不建立連接,當(dāng)它想傳送時(shí)就簡(jiǎn)單地去抓取來(lái)自應(yīng)用程序的數(shù)據(jù),并盡可能快地把它扔到網(wǎng)絡(luò)上。在發(fā)送端,UDP傳送數(shù)據(jù)的速度僅僅是受應(yīng)用程序生成數(shù)據(jù)的速度、計(jì)算機(jī)的能力和傳輸帶寬的限制;在接收端,UDP把每個(gè)消息段放在隊(duì)列中,應(yīng)用程序每次從隊(duì)列中讀一個(gè)消息段。
由于傳輸數(shù)據(jù)不建立連接,因此也就不需要維護(hù)連接狀態(tài),包括收發(fā)狀態(tài)等,因此一臺(tái)服務(wù)機(jī)可同時(shí)向多個(gè)客戶機(jī)傳輸相同的消息。
UDP信息包的標(biāo)題很短,只有8個(gè)字節(jié),相對(duì)于TCP的20個(gè)字節(jié)信息包而言UDP的額外開(kāi)銷很小。
吞吐量不受擁擠控制算法的調(diào)節(jié),只受應(yīng)用軟件生成數(shù)據(jù)的速率、傳輸帶寬、源端和終端主機(jī)性能的限制。
UDP是面向報(bào)文的。發(fā)送方的UDP對(duì)應(yīng)用程序交下來(lái)的報(bào)文,在添加首部后就向下交付給IP層。既不拆分,也不合并,而是保留這些報(bào)文的邊界,因此,應(yīng)用程序需要選擇合適的報(bào)文大小。
雖然UDP是一個(gè)不可靠的協(xié)議,但它是分發(fā)信息的一個(gè)理想?yún)f(xié)議。例如,在屏幕上報(bào)告股票市場(chǎng)、顯示航空信息等等。UDP也用在路由信息協(xié)議RIP(Routing Information Protocol)中修改路由表。在這些應(yīng)用場(chǎng)合下,如果有一個(gè)消息丟失,在幾秒之后另一個(gè)新的消息就會(huì)替換它。UDP廣泛用在多媒體應(yīng)用中。
TCP和UDP區(qū)別
TCP 是面向連接的傳輸控制協(xié)議,而UDP 提供了無(wú)連接的數(shù)據(jù)報(bào)服務(wù);
TCP 具有高可靠性,確保傳輸數(shù)據(jù)的正確性,不出現(xiàn)丟失或亂序,而UDP 在傳輸數(shù)據(jù)前不建立連接,不對(duì)數(shù)據(jù)報(bào)進(jìn)行檢查與修改,無(wú)須等待對(duì)方的應(yīng)答,所以會(huì)出現(xiàn)分組丟失、重復(fù)、亂序,應(yīng)用程序需要負(fù)責(zé)傳輸可靠性方面的所有工作;
UDP 具有較好的實(shí)時(shí)性,工作效率較 TCP 協(xié)議高;
UDP 段結(jié)構(gòu)比 TCP 的段結(jié)構(gòu)簡(jiǎn)單,因此網(wǎng)絡(luò)開(kāi)銷也??;
TCP 協(xié)議可以保證接收端毫無(wú)差錯(cuò)地接收到發(fā)送端發(fā)出的字節(jié)流,為應(yīng)用程序提供可靠的通信服務(wù)。對(duì)可靠性要求高的通信系統(tǒng)往往使用 TCP 傳輸數(shù)據(jù)。
應(yīng)用
適用場(chǎng)合
在選擇UDP作為傳輸協(xié)議時(shí)必須要謹(jǐn)慎。在網(wǎng)絡(luò)質(zhì)量令人十分不滿意的環(huán)境下,UDP協(xié)議數(shù)據(jù)包丟失會(huì)比較嚴(yán)重。但是由于UDP的特性:它不屬于連接型協(xié)議,因而具有資源消耗小,處理速度快的優(yōu)點(diǎn),所以通常音頻、視頻和普通數(shù)據(jù)在傳送時(shí)使用UDP較多,因?yàn)樗鼈兗词古紶杹G失一兩個(gè)數(shù)據(jù)包,也不會(huì)對(duì)接收結(jié)果產(chǎn)生太大影響。比如我們聊天用的ICQ和QQ就是使用的UDP協(xié)議。
實(shí)際應(yīng)用
在現(xiàn)場(chǎng)測(cè)控領(lǐng)域,面向的是分布化的控制器、監(jiān)測(cè)器等,其應(yīng)用場(chǎng)合環(huán)境比較惡劣,這樣就對(duì)待傳輸數(shù)據(jù)提出了不同的要求,如實(shí)時(shí)、抗干擾性、安全性等?;诖?,現(xiàn)場(chǎng)通信中,若某一應(yīng)用要將一組數(shù)據(jù)傳送給網(wǎng)絡(luò)中的另一個(gè)節(jié)點(diǎn),可由UDP進(jìn)程將數(shù)據(jù)加上報(bào)頭后傳送給IP進(jìn)程,UDP協(xié)議省去了建立連接和拆除連接的過(guò)程,取消了重發(fā)檢驗(yàn)機(jī)制,能夠達(dá)到較高的通信速率。
代碼演示
簡(jiǎn)單的一個(gè)客戶端/服務(wù)端數(shù)據(jù)收發(fā)的例子
UDP客戶端:
public class UdpClient { public static void main(String[] args) throws IOException { //建立一個(gè)socket DatagramSocket socket = new DatagramSocket(); //創(chuàng)建一個(gè)數(shù)據(jù)包 String msg = "你好啊,服務(wù)器~"; InetAddress localhost = InetAddress.getByName("localhost"); int port = 9090; DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port); //發(fā)送數(shù)據(jù)包 socket.send(packet); //關(guān)閉流 socket.close(); } }
UDP服務(wù)端:
public class UdpServer { public static void main(String[] args) throws IOException { //開(kāi)啟端口 DatagramSocket socket = new DatagramSocket(9090); //接收數(shù)據(jù)包 byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length); //阻塞接收 socket.receive(packet); String msg = new String(packet.getData(),0,packet.getLength()); System.out.println("接收到客戶端發(fā)來(lái)的數(shù)據(jù):" + msg); //關(guān)閉數(shù)據(jù)流 socket.close(); } }
模擬一個(gè)學(xué)生和老師的聊天對(duì)話
//客戶端 public class TalkSend implements Runnable { DatagramSocket socket = null; BufferedReader br = null; private int formPort; private String toIp; private int toPort; public TalkSend(int formPort, String toIp, int toPort) { this.formPort = formPort; this.toIp = toIp; this.toPort = toPort; try { socket = new DatagramSocket(this.formPort); //準(zhǔn)備數(shù)據(jù) 控制臺(tái)讀取System.in br = new BufferedReader(new InputStreamReader(System.in)); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true) { try { String msg = br.readLine(); byte[] bytes = msg.getBytes(); DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIp, this.toPort)); //發(fā)送數(shù)據(jù) socket.send(packet); if (msg.equals("bye")) { break; } } catch (IOException e) { e.printStackTrace(); } } socket.close(); } }
//服務(wù)端 public class TalkReceive implements Runnable { DatagramSocket socket = null; private int port; private String msgForm; public TalkReceive(int port, String msgForm) { this.port = port; this.msgForm = msgForm; try { socket = new DatagramSocket(port); } catch (SocketException e) { e.printStackTrace(); } } @Override public void run() { while (true) { try { //準(zhǔn)備接收包裹 byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length); socket.receive(packet); //斷開(kāi)連接 bye String msg = new String(packet.getData(), 0, packet.getLength()); System.out.println(msgForm + ":" + msg); if ("bye".equals(msg)) { break; } } catch (IOException e) { e.printStackTrace(); } } socket.close(); } }
public class TalkStudent { public static void main(String[] args) { new Thread(new TalkSend(7777,"localhost",8888)).start(); new Thread(new TalkReceive(9999,"老師")).start(); } }
public class TalkTeacher { public static void main(String[] args) { new Thread(new TalkSend(5555,"localhost",9999)).start(); new Thread(new TalkReceive(8888,"學(xué)生")).start(); } }
測(cè)試一下,結(jié)果如下:
總結(jié)
- UDP用戶數(shù)據(jù)報(bào)協(xié)議,是面向無(wú)連接的通訊協(xié)議,UDP數(shù)據(jù)包括目的端口號(hào)和源端口號(hào)信息,由于通訊不需要連接,所以可以實(shí)現(xiàn)廣播發(fā)送。
- UDP通訊時(shí)不需要接收方確認(rèn),屬于不可靠的傳輸,可能會(huì)出現(xiàn)丟包現(xiàn)象,實(shí)際應(yīng)用中要求程序員編程驗(yàn)證。
到此這篇關(guān)于Java網(wǎng)絡(luò)編程之UDP協(xié)議詳細(xì)解讀的文章就介紹到這了,更多相關(guān)UDP協(xié)議內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用IDEA搭建Hadoop開(kāi)發(fā)環(huán)境的操作步驟(Window10為例)
經(jīng)過(guò)三次重裝,查閱無(wú)數(shù)資料后成功完成hadoop在win10上實(shí)現(xiàn)偽分布式集群,以及IDEA開(kāi)發(fā)環(huán)境的搭建。一步一步跟著本文操作可以避免無(wú)數(shù)天坑2021-07-07IDEA 工程里 new不出來(lái)Vue文件的圖文解決方案
這篇文章主要介紹了IDEA 工程里 new不出來(lái)Vue文件的解決方案,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03IntelliJ IDEA(或者JetBrains PyCharm)中彈出"IntelliJ IDEA License
今天小編就為大家分享一篇關(guān)于IntelliJ IDEA(或者JetBrains PyCharm)中彈出"IntelliJ IDEA License Activation"的解決辦法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10Spring?Cloud?Gateway動(dòng)態(tài)路由Apollo實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Spring?Cloud?Gateway動(dòng)態(tài)路由通過(guò)Apollo實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10詳解Java中使用ImageIO類對(duì)圖片進(jìn)行壓縮的方法
這篇文章主要介紹了Java中使用ImageIO類對(duì)圖片進(jìn)行壓縮的方法,能夠按指定的比例調(diào)整圖片的寬高,需要的朋友可以參考下2016-04-04Java邏輯運(yùn)算符之&&、||?與&、?|的區(qū)別及應(yīng)用
這篇文章主要介紹了Java邏輯運(yùn)算符之&&、||?與&、?|的區(qū)別及應(yīng)用的相關(guān)資料,分別是&&、||?與&、?|,并探討了它們?cè)诓煌瑧?yīng)用場(chǎng)景中的表現(xiàn)和優(yōu)化效果,需要的朋友可以參考下2025-03-03Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件 FTP本地文件管理模塊實(shí)現(xiàn)(9)
這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單FTP軟件,F(xiàn)TP本地文件管理模塊的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04java代碼實(shí)現(xiàn)斗地主發(fā)牌功能
這篇文章主要介紹了java實(shí)現(xiàn)斗地主發(fā)牌功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11