网站首页 > 基础教程 正文
/**
* UDP协议,TCP/IP协议族中的协议,面向无连接,通信不需要建立连接(三次握手四次挥手),可能发生丢包乱序错包重复包,效率高于TCP,常用于游戏和视频通话
*/
public class DatagramPacket1 {
public static void main(String[] args) {
//UDP同样需要先创建服务端/接收方
DatagramSocket ds = null;
try {
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
//datagram数据报packet包,UDP使用数据报包封装数据,发送方发送数据报包,接收方接收数据报包
//服务端/接收方的数据报包对象的构造器需要:用于存放接收到的数据的字节数组byte[]、字节数组的可用长度(还可以指定存放的起始位置offset,不写默认从0位开始)
ds = new DatagramSocket(9999);
//通过DatagramSocket类发送/接收数据报包,需要指定端口用于发送/接收
ds.receive(dp);
//.receive(DatagramPacket)阻塞,等待接收数据,将收到的数据放入准备好的接收用数据报包中
System.out.println(new String(dp.getData(),dp.getOffset(),dp.getLength()));
//.getData()返回数据报包中的字节数据,new String(byte[])将数据转为字符串,因为数组可能没有放满,所以需要指定长度
//.getOffset()返回数据开始位置 .getLength()返回数据实际长度
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (ds != null) {
ds.close();
//DatagramSocket使用端口,用完需要关闭通道
}
}
}
}
class UDPClient{
public static void main(String[] args) {
//通过客户端/发送方发送数据
byte[] data = "将需要发送的数据转换为字节数组".getBytes();
DatagramPacket dp = null;
try {
dp = new DatagramPacket(data,0,data.length,InetAddress.getLocalHost(),9999);
//客户端/发送方构造器需要:存放了要发送的数据的字节数组、数据起始位置offset(不写默认从0位开始)、数据实际长度、用于指定发送地址IP:port的SocketAddress抽象类(子类为InetSocketAddress)(也可以用InetAddress指定ip,再加int port指定端口)
//接收方不需要指定地址,发送方需要指定地址
try(DatagramSocket ds = new DatagramSocket(8888)) {
//与TCP不同的是,UDP发送方和接收方使用同一个类DatagramSocket,因为不需要建立连接,所以从一开始双方即为平等的,既可以发也可以接,也可以通过数据报包指定不同的地址群发
//这里是客户端/发送方使用8888端口向 本机地址:9999端口发送数据报包
ds.send(dp);
/*
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
发送基本数据类型,先将基本数据写入数组,再将数组封包,发送
dos.writeLong(1000L);
dos.writeChar('a');
dos.writeUTF("接收方也需要按写入的顺序读取各个数据类型");
dos.flush();
byte[] data2 = baos.toByteArray();
ds.send(new DatagramPacket(data2,data2.length,new InetSocketAddress("127.0.0.1",9999)));
*/
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}
class Person implements Serializable{
//使用UDP发送对象,要发送的对象必须实现Serializable接口
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class SendObject{
public static void main(String[] args) {
Person p = new Person("qian",20);
byte[] obj = null;
try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(p);
oos.flush();
obj = baos.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
DatagramPacket dp = new DatagramPacket(obj,obj.length,new InetSocketAddress("127.0.0.1",9999));
try(DatagramSocket ds = new DatagramSocket(8888)) {
ds.send(dp);
} catch (IOException e) {
throw new RuntimeException(e);
}
//接收方也需要有这个类才能使用ObjectInputStream正确读取
}
}
猜你喜欢
- 2024-11-17 第三篇 hadoop的核心概念&存取策略
- 2024-11-17 Java 17 的 I/O 基础 OutputStream 篇
- 2024-11-17 数据湖(十七):Flink与Iceberg整合DataStream API操作
- 2024-11-17 JavaSE---02(javase下载安装教程)
- 2024-11-17 每秒8.8亿次请求!Lindorm让数据存得起,看得见
- 2024-11-17 Java IO: 文件读写与数据流操作(java文件读取和写入实例)
- 2024-11-17 面试官:请说下适配器模式、代理模式和装饰者模式的不同
- 2024-11-17 HDFS和NFS的架构及原理(hdfs fs -ls)
- 2024-11-17 这篇文章过后,别说你不懂NIO(这篇文章告诉你答案)
- 2024-11-17 java数据字节流(java 字节流 字符流)
- 最近发表
- 标签列表
-
- jsp (69)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- pythonif (86)
- location.href (69)
- dockerexec (65)
- tail-f (79)
- queryselectorall (63)
- location.search (79)
- bootstrap教程 (74)
- deletesql (62)
- linuxgzip (68)
- 字符串连接 (73)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)