UDP通信程序编写
发送数据
用发快递来做比喻,用UDP发送数据可以拆分为以下几个步骤:
需要使用DatagramSocket创建UDP连接,然后使用DatagramPacket打包要发送的数据,示例代码:
import java.io.IOException;
import java.net.*;
public class UDPSendingMsgDemo {
public static void main(String[] args) throws IOException {
// 发送数据
//1.创建DatagramSocket对象(快递公司)
// 细节:
//绑定端口,以后我们就是通过这个端口往外发送
// 空参:所有可用的端口中随机一个进行使用
// 有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
// 2.打包数据
// 使用DatagramPacket类
// 需要指定消息内容、消息大小、IP地址、端口号
String str = "你好,世界"; // 要发送的消息
byte[] bytes = str.getBytes(); // 转换为字节数组
InetAddress address = InetAddress.getByName("127.0.0.1"); // 获取目的地IP地址对象
int port = 10086; // 指定端口号
// 创建UDP数据包对象
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
// 3.发送数据
ds.send(dp);
// 4.释放资源
ds.close(); // 关闭连接
}
}
接收数据
用收快递来比如,可以拆分为如下步骤:
接收时也需要使用到DatagramSocket类和DatagramPacket类, 但是在接收时,DatagramSocket不需指定IP。代码如下:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceivingMsgDemo {
public static void main(String[] args) throws IOException {
// 接收数据
//1.创建DatagramSocket对象(快递公司)
// 细节:
//在接收的时候,一定要绑定端口
// 而且绑定的端口一定要跟发送的端口保持一致
DatagramSocket ds = new DatagramSocket(10086);
// 2.接收数据包
byte[] bytes = new byte[1024]; // 创建用于接收数据的缓冲数组
DatagramPacket dp = new DatagramPacket(bytes, bytes.length); // 用于接收数据的数据包对象
// DatagramPacket dp = new DatagramPacket(bytes, 0, bytes.length);
ds.receive(dp); // 接收数据,该方法返回值为void
// 该方法是阻塞的,在执行到这里时会死等
// 等待接收消息
// 3.解析数据包
byte[] data = dp.getData(); // 接收到的数据
int len = dp.getLength(); // 接收数据的长度
InetAddress address = dp.getAddress(); // 发送端的IP地址
int port = dp.getPort();// 发送端的接口号
System.out.println("接收到数据:" + new String(data, 0, len));
System.out.println("该数据是从" + address + "的端口" + port + "上发出的。");
}
}
UDP通信小练习
聊天室小程序,按照下面的要求实现程序
UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Receive {
public static void main(String[] args) throws IOException {
// 接收数据并回显
// 创建连接,并监听10086端口
DatagramSocket dSocket = new DatagramSocket(10086);
System.out.println("聊天室已开启!");
byte[] bytes = new byte[64 * 1024]; // 用于接收消息缓冲
// 创建数据包对象,并指定bytes数组为缓冲数组
DatagramPacket dPacket = new DatagramPacket(bytes, bytes.length);
// 循环接收消息
while (true){
// 接收数据
dSocket.receive(dPacket);
// 回显消息
// 源地址
InetAddress srcAddr = dPacket.getAddress();
// 源端口
int srcPort = dPacket.getPort();
// 获取接收到的数据
byte[] data = dPacket.getData();
// 获取接收到的数据长度
int len = dPacket.getLength();
// 显示数据
System.out.println("来自" + srcAddr + ":" + srcPort + "的消息:");
System.out.println(new String(data, 0, len));
//System.out.println(new String(bytes, 0, len));
}
}
}
发送端:
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class Send {
public static void main(String[] args) throws IOException {
// 目标地址和端口
InetAddress address = InetAddress.getByName("localhost");
int port = 10086;
// 创建连接
DatagramSocket dSocket = new DatagramSocket();
// 发送提示消息
/*
StringBuffer hintStr = new StringBuffer();
hintStr.append(new String(InetAddress.getLocalHost().getAddress()));
hintStr.append("已上线!");
DatagramPacket olHint = new DatagramPacket(hintStr.toString().getBytes(), hintStr.toString().getBytes().length, address, port);
dSocket.send(olHint);
*/
// 使用循环不断发送数据
while (true) {
// 读取键盘输入
System.out.println("请输入聊天内容:");
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
if ("886".equals(input)){
// 结束程序
System.out.println("退出聊天室。");
dSocket.close(); // 关闭连接
break;
}else {
// 创建数据包并发送
// 创建数据包对象
byte[] bytes = input.getBytes();
// 创建数据包并指定地址和端口号
DatagramPacket dPacket = new DatagramPacket(bytes, bytes.length, address, port);
// 发送数据
dSocket.send(dPacket);
System.out.println("消息已发送");
}
}
}
}
UDP的三种通信方式
单播
之前按照指定IP地址的方式即为单播。这里不再赘述。
组播
组播地址:224.0.0.0~239.255.255.255
其中224.0.0.0~224.0.0.255为预留的组播地址
在Java中如果使用多播,则需要使用MulticastSocket类的对象进行通信。在指定IP时需要使用多播(这里是组播)地址。
在接受和发送端都需要使用组播地址进行消息的接受和发送。
发送端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class MulticastSenderTest {
public static void main(String[] args) throws IOException {
/*
组播发送端代码
*/
// 创建MulticastSocket对象
MulticastSocket mSocket = new MulticastSocket();
// 创建DatagramPacket对象
String msg = "你好,组播!";
byte[] bytes = msg.getBytes(); // 获取消息的字节码数组
InetAddress address = InetAddress.getByName("224.0.0.2"); //获取地址
int port = 10000;
// 创建数据包, 指定消息内容、消息长度、目标地址、目的端口
DatagramPacket dPacket = new DatagramPacket(bytes, bytes.length, address, port);
// 调用MulticastSocket发送数据
mSocket.send(dPacket);
// 关闭链接
mSocket.close();
}
}
接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class MulticastReceiverTest {
public static void main(String[] args) throws IOException {
/*
组播接收端代码
*/
// 1. 创建MulticastSocket对象, 指定监听的端口
MulticastSocket mSocket = new MulticastSocket(10000);
// 2.将当前主机,添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.0.0.2");
mSocket.joinGroup(address); // 此方法自JDK14启用
// 3.创建DatagramPacket数据包对象
byte[] bytes = new byte[1024];
DatagramPacket dPacket = new DatagramPacket(bytes, 0, bytes.length);
// 4.接受数据
mSocket.receive(dPacket);
// 5.解析数据
int len = dPacket.getLength(); // 取得消息的长度
String hostAddress = dPacket.getAddress().getHostAddress();
String hostName = dPacket.getAddress().getHostName();
System.out.println("IP为:" + hostAddress + ",主机名为:" + hostName + "的人,发送了数据:" + new String(bytes, 0, len));
// 6.释放资源
mSocket.close();
}
}
广播
广播地址:255.255.255.255