1. 程式人生 > >7.3(java學習筆記)網路程式設計之UDP

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