UDP通信的实现和项目案例
UDP通信实现原理
UDP协议与之前讲到的TCP协议不同,是面向无连接的,双方不需要建立连接便可通信。UDP通信所发送的数据需要进行封包操作(使用DatagramPacket类),然后才能接收或发送(使用DatagramSocket类)。
DatagramPacket:数据容器(封包)的作用
此类表示数据报包。 数据报包用来实现封包的功能。
常用方法:
方法名 | 使用说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造数据报包,用来接收长度为 length 的数据包 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 |
getAddress() | 获取发送或接收方计算机的IP地址,此数据报将要发往该机器或者是从该机器接收到的 |
getData() | 获取发送或接收的数据 |
setData(byte[] buf) | 设置发送的数据 |
DatagramSocket:用于发送或接收数据报包
当服务器要向客户端发送数据时,需要在服务器端产生一个DatagramSocket对象,在客户端产生一个DatagramSocket对象。服务器端的DatagramSocket将DatagramPacket发送到网络上,然后被客户端的DatagramSocket接收。
DatagramSocket有两种常用的构造函数。一种是无需任何参数的,常用于客户端;另一种需要指定端口,常用于服务器端。如下所示:
- DatagramSocket() :构造数据报套接字并将其绑定到本地主机上任何可用的端口。
- DatagramSocket(int port) :创建数据报套接字并将其绑定到本地主机上的指定端口。
常用方法:
方法名 | 使用说明 |
---|---|
send(DatagramPacket p) | 从此套接字发送数据报包 |
receive(DatagramPacket p) | 从此套接字接收数据报包 |
close() | 关闭此数据报套接字 |
UDP通信编程基本步骤:
- 创建客户端的DatagramSocket,创建时,定义客户端的监听端口。
- 创建服务器端的DatagramSocket,创建时,定义服务器端的监听端口。
- 在服务器端定义DatagramPacket对象,封装待发送的数据包。
- 客户端将数据报包发送出去。
- 服务器端接收数据报包。
UDP通信入门案例
创建服务端
public class UDPServer {public static void main(String[] args) {//创建服务端接收数据的DatagramSocket对象try(DatagramSocket datagramSocket = new DatagramSocket(9999)){//创建数据缓存区byte[] b = new byte[1024];//创建数据报包对象DatagramPacket dp =new DatagramPacket(b,b.length);//等待接收客户端所发送的数据datagramSocket.receive(dp);String str = new String(dp.getData(),0,dp.getLength());System.out.println(str);}catch(Exception e){e.printStackTrace();}}
}
创建客户端
public class UDPClient {public static void main(String[] args) {//创建数据发送对象 DatagramSocket,需要指定消息的发送端口try(DatagramSocket ds = new DatagramSocket(8888)) {//消息需要进行类型转换,转换成字节数据类型。byte[] b = "打酱油".getBytes();//创建数据报包装对象DatagramPacketDatagramPacket dp = new DatagramPacket(b, b.length, new InetSocketAddress("127.0.0.1", 9999));//发送消息ds.send(dp);}catch(Exception e){e.printStackTrace();}}
}
UDP协议传递基本数据类型
创建服务端
public class BasicDataUDPServer {public static void main(String[] args) {try(DatagramSocket datagramSocket =new DatagramSocket(9999);){//创建字节数组缓冲区byte[] bytes = new byte[1024];//创建datagramPacket存放字节数组类型的数据DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);//等待客户端传入数据datagramSocket.receive(datagramPacket);//实现数据类型转换try(DataInputStream dataInputStream =new DataInputStream(new ByteArrayInputStream(bytes))){//通过基本数据数据流对象获取传递的数据System.out.println(dataInputStream.readLong());}}catch (Exception e){e.printStackTrace();}}
}
创建客户端
public class BasicDataUDPClient {public static void main(String[] args) {//创建发送数据的DatagramSocket对象try(DatagramSocket datagramSocket = new DatagramSocket(8856);//创建将基本数据类型转换为字节数组的ByteArrayOutputStream对象ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();//创建将基本数据类型写入ByteArrayOutputStream中的数据输出流对象DataOutputStream dataOutputStream =new DataOutputStream(byteArrayOutputStream)){//要传递的数据long data=10000l;//写入ByteArrayOutputStream对象dataOutputStream.writeLong(data);//将基本数据类型转换为字节数组byte[] byteArray = byteArrayOutputStream.toByteArray();//将字节数组包装到 DatagramPacket中DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length, new InetSocketAddress("127.0.0.1",9999));//发送数据datagramSocket.send(datagramPacket);}catch (Exception e){e.printStackTrace();}}
}
传递自定义对象类型
创建Person类
/*** 当该对象需要在网络上传输时,一定要实现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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
创建服务端
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);//接收数据datagramSocket.receive(datagramPacket);//数据类型转换try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(datagramPacket.getData()))){Person person = (Person)ois.readObject();System.out.println(person);}}catch (Exception e){e.printStackTrace();}}
}
创建客户端
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);//将自定义数据类型转换为字节数组类型byte[] byteArray = bos.toByteArray();//将自定义数据类型包装到DatagramPacket中DatagramPacket datagramPacket=new DatagramPacket(byteArray,byteArray.length,new InetSocketAddress("127.0.0.1",9999));//发送数据datagramSocket.send(datagramPacket);}catch (Exception e){e.printStackTrace();}}
}