7.3(java學習筆記)網路程式設計之UDP
一、UDP
UDP的全稱是User Datagram Protocol(使用者資料報協議),是一種無連線的不安全的傳輸協議,
傳輸資料時傳送方和接收方無需建立連線,所以是不安全的。
傳送時不建立連線直接傳送,傳送後不關注接受方能否接到。UDP只負責發出去,後續的事情與之無關。
1)、使用UDP傳送和接受資料的過程:
1接收資料:
1.1建立資料包例項,用於接收資料。(指定接收方IP,埠)
1.2建立接收容器
1.3將接收容器封裝成包
1.4接收包
1.5處理包(可以看做拆包,將包中資料拿出來)
1.6釋放資源
2.傳送資料
2.1建立資料報例項,用於傳送資料。(指定傳送IP,埠)
2.2建立傳送資源
2.3將傳送資源封裝成包(包加上傳送目的地,埠)
2.4傳送包
2.5釋放資源
2)、DatagramSocket & DatagramPacket
java中將UDP封裝成DatagramSocket類,用於傳送和接收資料報。
2.1構造方法:
DatagramSocket(int port)//建立資料報,並繫結到本地主機的指定埠
DatagramSocket(int port, InetAddress laddr)//建立資料報,繫結到指定地址的指定埠
2.2主要方法
void send(DatagramPacket p)//傳送資料包
void receive(DatagramPacket p)//接收資料包
資料需要打包後才能傳送,而接收資料也是以包的形式接收,java中使用DatagramPacket將資料打包。
構造方法:
DatagramPacket(byte[] buf, int length)//構造接收資料包及其長度,(設定接收資料包)
DatagramPacket(byte[] buf, int length, InetAddress address, int port)//構造一個數據包,指定傳送主機及埠資訊(設定傳送資料包)
主要方法:
int getLength()//返回要傳送的或者要接受的資料長度
byte[] getData()//獲取發生或接受的資料,相當於拆包,獲取包內資料。
Server:(接收資料)
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; public class Server { public static void main(String[] args) throws IOException { DatagramSocket server = new DatagramSocket(8888,InetAddress.getByName("localhost")); byte[] r = new byte[1024];//接收容器 DatagramPacket packet = new DatagramPacket(r,r.length);//打包 server.receive(packet);//接收包 System.out.println(new String(packet.getData(),0,packet.getLength()));//拆包並解析包 server.close(); } }
Client:(傳送資料)
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; public class Client { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub DatagramSocket client = new DatagramSocket(8887,InetAddress.getByName("localhost")); String msg = "hello udp"; byte[] b_msg = msg.getBytes();//資料-->位元組
//打包,並加上目的地資訊 DatagramPacket packet = new DatagramPacket(b_msg,b_msg.length,InetAddress.getByName("localhost"),8888); client.send(packet);//傳送包 client.close();//釋放資源 } }
執行結果:
hello udp
先執行Server,Server會等待資料,之後執行Client傳送資料,Server接收到資料後就會解析。
想象成寄快遞1.東西準備好(準備資料),
2.轉換為固定格式(資料轉換為位元組)
3.然後打包,包上貼快遞單(郵寄的目的地(IP)和接收人(埠))
4.然後傳送,
5.接收方接收
6.然後拆快遞(拆包)
7.然後拿到東西。(位元組轉換資料)
上面的資料是字串可以直接轉換為位元組,但如果有時候傳輸的資料不能直接轉換為位元組這時該怎麼辦呢?
這就要用到IO流的知識,主要使用ByteArrayStream(toByteArray()方法)、DataStream(WriteXxxx()方法)。
資料-->位元組:
先將資料及其格式通過DataOutputStream寫入ByteArrayOutputStream中,再通過ByteArrayOutputStream中的toByteArray()方法將的位元組拿出。
位元組-->資料:
將位元組陣列放入ByteArrayInputStream中,然後通過DataInputStream中的readXxx讀取ByteArrayInputStream中位元組陣列,將其轉換為對應資料型別。
Server:
import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Server { public static void main(String[] args) throws IOException { DatagramSocket server = new DatagramSocket(8888,InetAddress.getByName("localhost")); byte[] r = new byte[1024]; DatagramPacket packet = new DatagramPacket(r,r.length); server.receive(packet); System.out.println(byteToDouble(packet.getData()));//位元組轉換為陣列 server.close(); } public static double byteToDouble(byte[] b) throws IOException{ ByteArrayInputStream bis = new ByteArrayInputStream(b);//將位元組放入ByteArratInputStream中 DataInputStream dis = new DataInputStream(bis);//通過dis讀取bis中位元組 double data = dis.readDouble();//通過dis.readXxxx讀取bis中的位元組陣列。 return data; } }
Client:
import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Client { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub DatagramSocket client = new DatagramSocket(8887,InetAddress.getByName("localhost")); // String msg = "hello udp"; Double data = 9.1; byte[] b_data = doubleToByte(data);//資料轉換為位元組 DatagramPacket packet = new DatagramPacket(b_data,b_data.length,InetAddress.getByName("localhost"),8888); client.send(packet); client.close(); } public static byte[] doubleToByte(double dou) throws IOException{ ByteArrayOutputStream bos = new ByteArrayOutputStream();//建立位元組陣列輸入流 DataOutputStream dos = new DataOutputStream(bos);//通過dos想bos中寫入 dos.writeDouble(dou);//通過dos中的write.Xxxx將dou寫入bos中 dos.flush(); dos.close(); byte[] data = bos.toByteArray();//將bos中位元組取出。 return data; } }
執行結果:
9.1