JAVA深化篇_38—— UDP通信的實現(xiàn)和項目案例
UDP通信的實現(xiàn)和項目案例
UDP通信實現(xiàn)原理
UDP協(xié)議與之前講到的TCP協(xié)議不同,是面向無連接的,雙方不需要建立連接便可通信。UDP通信所發(fā)送的數(shù)據(jù)需要進行封包操作(使用DatagramPacket類),然后才能接收或發(fā)送(使用DatagramSocket類)。
DatagramPacket:數(shù)據(jù)容器(封包)的作用
此類表示數(shù)據(jù)報包。 數(shù)據(jù)報包用來實現(xiàn)封包的功能。
常用方法:
| 方法名 | 使用說明 |
|---|---|
| DatagramPacket(byte[] buf, int length) | 構(gòu)造數(shù)據(jù)報包,用來接收長度為 length 的數(shù)據(jù)包 |
| DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 構(gòu)造數(shù)據(jù)報包,用來將長度為 length 的包發(fā)送到指定主機上的指定端口號 |
| getAddress() | 獲取發(fā)送或接收方計算機的IP地址,此數(shù)據(jù)報將要發(fā)往該機器或者是從該機器接收到的 |
| getData() | 獲取發(fā)送或接收的數(shù)據(jù) |
| setData(byte[] buf) | 設(shè)置發(fā)送的數(shù)據(jù) |
DatagramSocket:用于發(fā)送或接收數(shù)據(jù)報包
當(dāng)服務(wù)器要向客戶端發(fā)送數(shù)據(jù)時,需要在服務(wù)器端產(chǎn)生一個DatagramSocket對象,在客戶端產(chǎn)生一個DatagramSocket對象。服務(wù)器端的DatagramSocket將DatagramPacket發(fā)送到網(wǎng)絡(luò)上,然后被客戶端的DatagramSocket接收。
DatagramSocket有兩種常用的構(gòu)造函數(shù)。一種是無需任何參數(shù)的,常用于客戶端;另一種需要指定端口,常用于服務(wù)器端。如下所示:
- DatagramSocket() :構(gòu)造數(shù)據(jù)報套接字并將其綁定到本地主機上任何可用的端口。
- DatagramSocket(int port) :創(chuàng)建數(shù)據(jù)報套接字并將其綁定到本地主機上的指定端口。
常用方法:
| 方法名 | 使用說明 |
|---|---|
| send(DatagramPacket p) | 從此套接字發(fā)送數(shù)據(jù)報包 |
| receive(DatagramPacket p) | 從此套接字接收數(shù)據(jù)報包 |
| close() | 關(guān)閉此數(shù)據(jù)報套接字 |
UDP通信編程基本步驟:
- 創(chuàng)建客戶端的DatagramSocket,創(chuàng)建時,定義客戶端的監(jiān)聽端口。
- 創(chuàng)建服務(wù)器端的DatagramSocket,創(chuàng)建時,定義服務(wù)器端的監(jiān)聽端口。
- 在服務(wù)器端定義DatagramPacket對象,封裝待發(fā)送的數(shù)據(jù)包。
- 客戶端將數(shù)據(jù)報包發(fā)送出去。
- 服務(wù)器端接收數(shù)據(jù)報包。
UDP通信入門案例
創(chuàng)建服務(wù)端
public class UDPServer {
public static void main(String[] args) {
//創(chuàng)建服務(wù)端接收數(shù)據(jù)的DatagramSocket對象
try(DatagramSocket datagramSocket = new DatagramSocket(9999)){
//創(chuàng)建數(shù)據(jù)緩存區(qū)
byte[] b = new byte[1024];
//創(chuàng)建數(shù)據(jù)報包對象
DatagramPacket dp =new DatagramPacket(b,b.length);
//等待接收客戶端所發(fā)送的數(shù)據(jù)
datagramSocket.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str);
}catch(Exception e){
e.printStackTrace();
}
}
}
創(chuàng)建客戶端
public class UDPClient {
public static void main(String[] args) {
//創(chuàng)建數(shù)據(jù)發(fā)送對象 DatagramSocket,需要指定消息的發(fā)送端口
try(DatagramSocket ds = new DatagramSocket(8888)) {
//消息需要進行類型轉(zhuǎn)換,轉(zhuǎn)換成字節(jié)數(shù)據(jù)類型。
byte[] b = "打醬油".getBytes();
//創(chuàng)建數(shù)據(jù)報包裝對象DatagramPacket
DatagramPacket dp = new DatagramPacket(b, b.length, new InetSocketAddress("127.0.0.1", 9999));
//發(fā)送消息
ds.send(dp);
}catch(Exception e){
e.printStackTrace();
}
}
}
UDP協(xié)議傳遞基本數(shù)據(jù)類型
創(chuàng)建服務(wù)端
public class BasicDataUDPServer {
public static void main(String[] args) {
try(DatagramSocket datagramSocket =new DatagramSocket(9999);){
//創(chuàng)建字節(jié)數(shù)組緩沖區(qū)
byte[] bytes = new byte[1024];
//創(chuàng)建datagramPacket存放字節(jié)數(shù)組類型的數(shù)據(jù)
DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);
//等待客戶端傳入數(shù)據(jù)
datagramSocket.receive(datagramPacket);
//實現(xiàn)數(shù)據(jù)類型轉(zhuǎn)換
try(DataInputStream dataInputStream =new DataInputStream(new ByteArrayInputStream(bytes))){
//通過基本數(shù)據(jù)數(shù)據(jù)流對象獲取傳遞的數(shù)據(jù)
System.out.println(dataInputStream.readLong());
}
}catch (Exception e){
e.printStackTrace();
}
}
}
創(chuàng)建客戶端
public class BasicDataUDPClient {
public static void main(String[] args) {
//創(chuàng)建發(fā)送數(shù)據(jù)的DatagramSocket對象
try(DatagramSocket datagramSocket = new DatagramSocket(8856);
//創(chuàng)建將基本數(shù)據(jù)類型轉(zhuǎn)換為字節(jié)數(shù)組的ByteArrayOutputStream對象
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
//創(chuàng)建將基本數(shù)據(jù)類型寫入ByteArrayOutputStream中的數(shù)據(jù)輸出流對象
DataOutputStream dataOutputStream =new DataOutputStream(byteArrayOutputStream)){
//要傳遞的數(shù)據(jù)
long data=10000l;
//寫入ByteArrayOutputStream對象
dataOutputStream.writeLong(data);
//將基本數(shù)據(jù)類型轉(zhuǎn)換為字節(jié)數(shù)組
byte[] byteArray = byteArrayOutputStream.toByteArray();
//將字節(jié)數(shù)組包裝到 DatagramPacket中
DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length
, new InetSocketAddress("127.0.0.1",9999));
//發(fā)送數(shù)據(jù)
datagramSocket.send(datagramPacket);
}catch (Exception e){
e.printStackTrace();
}
}
}
傳遞自定義對象類型
創(chuàng)建Person類
/**
* 當(dāng)該對象需要在網(wǎng)絡(luò)上傳輸時,一定要實現(xiàn)Serializable接口
*/
public class Person implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
創(chuàng)建服務(wù)端
public class Person {
public static void main(String[] args) {
try(DatagramSocket datagramSocket =new DatagramSocket(9999);){
byte[] bytes =new byte[1024];
DatagramPacket datagramPacket =new DatagramPacket(bytes,bytes.length);
//接收數(shù)據(jù)
datagramSocket.receive(datagramPacket);
//數(shù)據(jù)類型轉(zhuǎn)換
try (ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(datagramPacket.getData()))){
Person person = (Person)ois.readObject();
System.out.println(person);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
創(chuàng)建客戶端
public class ObjectTypeClient {
public static void main(String[] args) {
try(DatagramSocket datagramSocket =new DatagramSocket();
ByteArrayOutputStream bos =new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)){
//實例化Person對象
Person person =new Person();
person.setAge(18);
person.setName("zhangsan");
//寫入ByteArrayOutputStream對象
oos.writeObject(person);
//將自定義數(shù)據(jù)類型轉(zhuǎn)換為字節(jié)數(shù)組類型
byte[] byteArray = bos.toByteArray();
//將自定義數(shù)據(jù)類型包裝到DatagramPacket中
DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length,
new InetSocketAddress("127.0.0.1",9999));
//發(fā)送數(shù)據(jù)
datagramSocket.send(datagramPacket);
}catch (Exception e){
e.printStackTrace();
}
}
}
浙公網(wǎng)安備 33010602011771號