Java学习第二十天 网络编程—UDP

UDP通信

面向无连接、不可靠、速度快、将数据封装成包传输,数据包最大64k

UPD通信的过程就像是货运公司在两个码头之间发送货物一样,在码头发送和接收货物时都需要使用集装箱来装载货物。UPD通信也一样,发送和接收的数据也需要使用 " 集装箱 " 进行打包,为此JDK中提供了一个DatagramPacket类,该类的实例对象就相当于一个集装箱,用于封装UPD通信中发送或者接收的数据。

DatagramPacket(byte[] buf,int length)
使用该构造方法在创建DatagramPacket对象时,指定了封装数据的字节数组和数据的大小,没有指定IP地址和端口号。很明显,这样的对象只能用于接收端,不能用于发送端。因为发送端一定要明确指出数据的目的地(IP地址和端口号),而接收端不需要明确知道数据的来源,只需要接收到数据即可。

DatagramPacket(byte[] buf,int length,InetAddress address,int port)
使用该构造方法在创建DatagramPacket对象时,不仅指定了封装数据的字节数组和数据的大小,还指定了数据包的目标IP地址(addr)和端口号(port)。该对象通常用于发送端,因为在发送数据时必须指定接收端的IP地址和端口号,就好像发送货物的集装箱上面必须标明接收人的地址一样。
在这里插入图片描述
上面讲到DatagramPacket数据包的作用就如同 " 集装箱 ",可以将发送端或者接收端的数据封装起来。然而运输货物只有 " 集装箱 " 是不够的,还需要 " 码头 "。同理,在程序中,要实现通信,只有DatagramPacket数据包也是不行的,它也需要一个 " 码头 "。为此,JDK提供了一个DatagramSocket类,该类的作用就类似于 " 码头 ",使用这个类的实例对象就可以发送和接收DatagramPacket的数据包。

DatagramSocket(int port)
该构造方法即可用于创建接收端的DatagramSocket对象,又可以创建发送端的DatagramSocket对象,在创建接收端的DatagramSocket对象时,必须要指定一个端口号,这样就可以监听指定的端口。
在这里插入图片描述

UDP网络程序

上面讲解了DatagramPacket和DatagramSocket的相关知识,接下来通过一个案例来学习一下他们在程序中的具体用法。要实现UDP通信需要创建一个发送端程序和一个接收端程序,很明显,在通信时只有接收端程序先运行,才能避免发送端发送数据时找不到接收端而造成的数据丢失问题。

建立UDP主机A(接收方)编程模型:
1. 创建DatagramSocket类型的对象,并提供端口号
2. 创建DatagramPacket类型的对象,用于接收发送来的数据
3. 使用上述对象接收数据的内容,使用recieve()方法
4. 关闭相关资源

public class Example01 {
	public static void main(String[] args) throws Exception {
		//创建一个长度为1024的字节数组,用于放数据
		byte[] by = new byte[1024];
		//定义一个DatagramSocket对象,监听的端口号为8899;
		DatagramSocket ds = new DatagramSocket(8899);
		//定义一个DatagramPacket对象,用于接收数据
		DatagramPacket dp = new DatagramPacket(by, by.length);
		//等待接收数据,没有数组则会阻塞
		ds.receive(dp);
		//获取接收到的数据,包括数据内容、长度、发送端和IP地址和端口号
		String str = new String(dp.getData(),0,dp.getLength()) + " from "+dp.getAddress().getHostAddress()+":"+dp.getPort();
		System.out.println(str); 	//打印接收到的信息
		//关闭资源
		ds.close();
	}
}

运行接收端程序后,程序一直处于停滞状态,这是因为DatagramSocket的receive()方法在运行时会发生阻塞,只有接收到发送端程序发送的数据时,该方法才会结束这种阻塞状态,程序才会继续向下执行。

建立UDP主机B(发送方)编程模型:
1. 创建DatagramSocket类型的对象
2. 创建DatagramPacket类型的对象,并提供端口号和IP地址
3. 使用上述的对象发送数据内容,使用send()方法
4. 关闭相关资源

public class Example02 {
	public static void main(String[] args) throws Exception {
		//创建一个DatagramSocket对象,指定本地端口号
		DatagramSocket ds = new DatagramSocket(8520);
		//要发送的数据
		byte[] str="嘿嘿嘿".getBytes();
		//创建一个要发送的数据,指定数据、IP地址、端口号
		DatagramPacket dp = new DatagramPacket(str, str.length, InetAddress.getByName("localhost"), 8899);
		System.out.println("发送数据!");
		//发送数据
		ds.send(dp);
		//关闭资源
		ds.close();
	}
}

在接收端程序阻塞的状态下,运行发送端程序,接收端程序就会收到发送端发送的数据而结束阻塞状态,并打印接收到的数据。

需要注意的是,在创建发送端的DatagramSocket对象时,可以不指定端口号,程序中指定端口号的目的是为了每次运行时接收端的getPort()方法的返回值都是一直的,否则发送端的端口号由系统自动分配,接收端的getPort()方法的返回值每次都不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值