接收udp数据_聊聊UDP、TCP和实现一个简单的JAVA UDP小Demo
最近真的比較忙,很久就想寫了,可是一直苦于寫點什么,今天腦袋靈光一閃,覺得自己再UDP方面還有些不了解的地方,所以要給自己掃盲。
好了,咱們進入今天的主題,先列一下提綱:
1. UDP是什么,UDP適用于什么場景?
2. 寫一個小Demo來加深一下UDP的理解。
3. UDP和TCP的區(qū)別有哪些?
4. TCP建連和關閉的過程,為什么建立連接的時候是三次握手,斷開連接的時候需要四次?
1. UDP是什么,UDP適用于什么場景?
相信很多同學都聽過UDP,UDP的全稱:User Datagrame Protocol, 用戶報文協(xié)議,是一個傳輸層協(xié)議。UDP最大的特點是:不可靠網(wǎng)絡傳輸,無連接數(shù)據(jù)協(xié)議,即發(fā)送前不要連接,直接向目標地址發(fā)送。而TCP和UDP基本上是相互補充的,TCP是可靠的數(shù)據(jù)數(shù)據(jù)傳輸,基于連接后的數(shù)據(jù)發(fā)送。
TCP是Transmission Control Protocol,傳輸控制協(xié)議,TCP是基于可靠的數(shù)據(jù)傳輸,那么就需要犧牲更多的延遲和網(wǎng)絡帶寬。而UDP則不需要可靠的數(shù)據(jù)傳輸,那么將會需要更小的網(wǎng)絡延遲和網(wǎng)絡開銷。UDP可以允許丟棄延遲的數(shù)據(jù)包。由于低延遲低帶寬,所以UDP非常適合電腦游戲,語音電話,視頻電話,網(wǎng)絡直播。
我們接下來看一下UDP的Packet的組成(圖片來源網(wǎng)絡),8字節(jié)的Header,然后就是UDP的數(shù)據(jù)。本機如果作為客戶端的話,本機的端口號為0-65535,也就是本機連接外部機器的話最多可以連接65536,0是保留端口號。如果作為服務端的話,可以使用的端口為2的32次方個端口。也就是可以接收的數(shù)據(jù)可以有這么多。當然,目前一臺機器能處理的數(shù)據(jù)沒有這么多。
8字節(jié)的Header,很簡單也比較少,不像TCP需要20-60字節(jié)的數(shù)據(jù)。
Source port,源端口號,16位2個字節(jié)。
Length, 數(shù)據(jù)的長度2個字節(jié)。
Distination port, 目標端口,用于識別到目標機器的端口號。2個字節(jié)。
Checksum, 用于計算Header的Checksum(校驗值)。
2. 寫一個小Demo來加深一下UDP的理解。
1) UDP的服務端代碼,因為UDP的代碼都是JDK自帶的,所以也不需要引入其他jar包就可以。
2)Server端主要創(chuàng)建步驟:
a) 創(chuàng)建一個監(jiān)聽udp的端口號 8888.
b) 創(chuàng)建一個用于接收數(shù)據(jù)的DatagramPacket,參數(shù)有兩個,一個是數(shù)據(jù),一個是數(shù)據(jù)的長度。
c) 采用循環(huán)進行receive數(shù)據(jù),直到收到的bye字符串。
package myflink.udp;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;/** * @author huangqingshi * @Date 2020-05-24 */public class UDPServer { public static void main(String[] args) throws IOException { //1. 創(chuàng)建一個監(jiān)聽8888端口的udp socket DatagramSocket ds = new DatagramSocket(8888); //設置接收數(shù)據(jù)的最大值 byte[] receive = new byte[65535]; //用于接收的數(shù)據(jù) DatagramPacket datagramPacket = null; while(true) { //2. 創(chuàng)建一個用于接收數(shù)據(jù)。buf即數(shù)據(jù)和其長度 datagramPacket = new DatagramPacket(receive,receive.length ); //3. 接收byteBuff的數(shù)據(jù) ds.receive(datagramPacket); System.out.println("Client:-" + data(receive)); //4. 如果接收到了bye,程序結束 if("bye".equals(data(receive))) { break; } //5.清理receive中的數(shù)據(jù) receive = new byte[65535]; } } public static StringBuilder data(byte[] bytes) { if(bytes == null) { return null; } StringBuilder ret = new StringBuilder(); int i = 0; while (bytes[i] != 0) { ret.append((char) bytes[i]); i++; } return ret; }}3)接下來是客戶端的代碼,步驟如下:
a) 創(chuàng)建scanner用于在控制臺進行數(shù)據(jù)輸入,然后創(chuàng)建一個DatagramSocket用于處理數(shù)據(jù)。
b) 創(chuàng)建一個DatagramPacket用于數(shù)據(jù)的發(fā)送。
c) 進行數(shù)據(jù)發(fā)送。
d) 持續(xù)發(fā)送數(shù)據(jù),當收到bye字符串的話就會結束。
package myflink.udp;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.util.Scanner;/** * @author huangqingshi * @Date 2020-05-24 */public class UDPClient { public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); InetAddress ip = InetAddress.getLocalHost(); //1. 創(chuàng)建一個socket對象用于處理數(shù)據(jù) DatagramSocket socket = new DatagramSocket(); //用于存放數(shù)據(jù) byte[] buf = null; //一個死循環(huán),用于接收數(shù)據(jù)后處理,收到bye后結束處理 while(true) { String input = scanner.nextLine(); //將接收到的信息轉換為byte數(shù)組 buf = input.getBytes(); //2. 創(chuàng)建一個DatagramPack包用于創(chuàng)建發(fā)送的數(shù)據(jù) DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, ip, 8888); //3. 發(fā)送數(shù)據(jù) socket.send(datagramPacket); //4. 如果收到了byte直接結束循環(huán) if("bye".equals(input)) { break; } } }}啟動服務端和客戶端,然后再控制臺輸入一些測試數(shù)據(jù),看一下服務端的控制臺輸出:
客戶端輸入數(shù)據(jù) Hello UDP服務端的輸出數(shù)據(jù) Client:-Hello UDP好了Demo已經(jīng)執(zhí)行完了,非常簡單。
3. UDP和TCP的區(qū)別有哪些?
1. TCP是可靠的傳輸,而UDP是非可靠數(shù)據(jù)傳輸。因為可靠,所以需要更高的延遲和網(wǎng)絡帶寬。而UDP則不需要,所以比較適合語音、視頻電話等。
2. UDP的Header字節(jié)為8個字節(jié),非常少,而TCP需要至少20個字節(jié)。
3. TCP是全雙工的,即可以發(fā)送接收數(shù)據(jù),可以想象兩個人打電話,即可以聽到聲音又可以發(fā)送聲音。而UDP發(fā)送數(shù)據(jù)的時候才連接,發(fā)送完數(shù)據(jù)之后不會保留連接。
4. TCP是點對點連接的,而UDP是多對多進行數(shù)據(jù)傳輸。TCP以字節(jié)流形式發(fā)送,有擁塞控制,方式發(fā)送數(shù)據(jù)量太大擁塞。而UDP是以報文形式發(fā)送給目標機器,沒有擁塞控制。
4. TCP建連和關閉的過程,為什么建立連接的時候是三次握手,斷開連接的時候需要四次?
1)三次握手建立連接處理:
1. 首先創(chuàng)建連接時client需要發(fā)送一個SYN+隨機sequence給 server 端,這是客戶端的狀態(tài)是SYN_SENT狀態(tài)。
2. server收到數(shù)據(jù)后會回復一個SYN+ACK,ACK為接收到的sequence+1,同時再發(fā)送一個sequence。server的狀態(tài)為ACK_REVD。
3. client再把收到的sequnce+1作為ACK再給到服務端,然后服務端和客戶端的狀態(tài)都是ESTABLISHED。說明連接建立了。
第二步中的SYN和ACK可以同時發(fā)送,這兩個值同時發(fā)送不受影響,都可以建立連接。當然如果兩步分開發(fā)送也是可以的,但是由于可以節(jié)省一步發(fā)送,所以不用多費事。
2)四次握手關閉連接處理:
1. client發(fā)一個FIN和一個隨機的sequence給server,然后客戶端的狀態(tài)變?yōu)镕IN_WAIT_1狀態(tài)。
2. server收到了FIN后,狀態(tài)變?yōu)镃LOSE_WAIT,然后再把接收到的sequence+1和ACK標志返回給client。client收到ACK后變?yōu)镕IN_WAIT2狀態(tài)。
3. 然后server再次給client發(fā)送一個FIN+sequence給client,此時客戶端的狀態(tài)變?yōu)門IME_WAIT狀態(tài)。
4. client再把收到的sequence + 1發(fā)送給server, 此時server的狀態(tài)變?yōu)镃LOSED。此時連接正式斷開。
這是客戶端主動發(fā)起關閉連接的過程,還有同時發(fā)送FIN標志的情況。
1. client發(fā)送FIN+sequence給server端,狀態(tài)變?yōu)镕IN_WAIT_1。
2. server也發(fā)送FIN+sequence給client端,此時server的狀態(tài)變?yōu)镕IN_WAIT_1。client的接收FIN后變?yōu)镃LOSING,同時server也變?yōu)镃LOSING。
3. client發(fā)送ACK+接收到的sequence+1給server。client的狀態(tài)變?yōu)門IME_WAIT。
4. server同時也發(fā)送ACK+接收到的seqnce+1給client。此時client和server都變?yōu)镃LOSED。
整個過程是這么一個過程,那么為什么TCP連接的時候需要三次,而關閉的時候需要四次?
因為建立連接的時候SYN+ACK可以同時發(fā)送,不影響連接建立。而關閉的時候FIN+ACK不能合起來,因為TCP是雙向且全雙工連接。也就是client和server建立好連接后,client和server即能發(fā)送信息同時也能接收信息。當client發(fā)送FIN給server的時候,只能說明客戶端不給server發(fā)送數(shù)據(jù)了,但是不證明client不接收數(shù)據(jù),所以給到server后,server處理好之后說我也不給你發(fā)數(shù)據(jù)了(FIN)。然后我已經(jīng)你不給我發(fā)數(shù)據(jù)了(ACK),這個時候client收到后說知道了(ACK), 此時連接就關閉了。
好了,關于這篇就整理到這里,如果有不對的地方歡迎批評指正。
總結
以上是生活随笔為你收集整理的接收udp数据_聊聊UDP、TCP和实现一个简单的JAVA UDP小Demo的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 15怎么自己画元件_【技术】3.1(1)
- 下一篇: mysql数据库ip地址_MySQL数据