UDP程序设计步骤如下:
**1. 发送数据包:**
(1)使用`DatagramSocket()`创建一个数据包套接字;
(2)使用`DatagramPacket(byte[] buf, int offset, int length , InetAddress address , int port)`创建要发送的数据包;
(3)使用`DatagramSocket`类的`send()`发送数据包。
**2. 接收数据包:**
(1)使用`DatagramSocket(int port)`创建数据包套接字,绑定要指定端口;
(2)使用`DatagramPacket(byte[] buf, int length)`创建字节数组来接收数据包;
(3)使用`DatagramPacket`类的`receive()`接收UDP数据包。
下面是一个广播数据报程序。主机不断重复播出节目预报,可以保证加入到同一组的主机随时接收到广播信息。接收者将正在接收的信息放在左边的文本框中,将全部接收的信息放在右边的文本框中。
*使用eclipse创建两个独立的工作空间,然后分别编写发送端和接收端的程序,先运行发送端程序,再运行接收端程序。或者使用cmd来执行。*
**`net/server/UdpServer.java`**(发送端)
```java
package net.server;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
/**
* 发送端
* @version 2020/10/21
*
*/
public class UdpServer extends Thread{
private String weather = "节目预告:八点有大型晚会,请收听!";
private int count = 1;
private int port = 6000; // 指定端口
private InetAddress ipAddress = null; //表示IP地址的类
private MulticastSocket multicastSocket = null; //多点广播套接字
public UdpServer() {
try {
// 指定局域网广播组的IP地址 ,该IP必须在:224.0.0.0-239.255.255.255 范围内,不是你电脑的IP地址
ipAddress = InetAddress.getByName("224.255.10.0");
multicastSocket = new MulticastSocket(port);
multicastSocket.setTimeToLive(1); // 指定发送的范围为本地网络
multicastSocket.joinGroup(ipAddress); // 将IP地址加入广播组
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 该函数不需要调用,当调用start()时会自动调用
*/
public void run() {
while(true) {
// 要发送的数据包
DatagramPacket packet = null;
// 将字符串转换为字节数组
byte[] data = (weather+count++).getBytes();
// 将要发送的数据打包
packet = new DatagramPacket(data, data.length, ipAddress, port);
System.out.println(new String(data));
try {
multicastSocket.send(packet); // 发送数据
sleep(3000); // 每隔3000ms发送一次
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
UdpServer udp = new UdpServer();
udp.start(); // 启动线程,自动调用run()
}
}
```
**`net/client/UdpClient.java`**(接收端)
```
package net.client;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import javax.swing.*;
/**
* 接收端
* @version 2020/7/3
*
*/
public class UdpClient extends JFrame implements Runnable, ActionListener{
private int port = 6000; // 端口
private InetAddress ipAddress = null; // IP地址类
private MulticastSocket multicastSocket = null; // 多点广播套接字对象
private JButton ince = new JButton("开始接收");
private JButton stop = new JButton("停止接收");
private JTextArea inceAr = new JTextArea(10, 10);
private JTextArea inced = new JTextArea(10, 10);
private Thread thread;
private boolean b = false;
public UdpClient() {
super("广播数据报");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
thread = new Thread(this);
ince.addActionListener(this);
stop.addActionListener(this);
inceAr.setForeground(Color.blue);
JPanel north = new JPanel();
north.add(ince);
north.add(stop);
add(north, BorderLayout.NORTH);
JPanel center = new JPanel();
center.setLayout(new GridLayout(1, 2));
center.add(inceAr);
center.add(inced);
add(center, BorderLayout.CENTER);
validate(); // 刷新窗口组件
try {
ipAddress = InetAddress.getByName("224.255.10.0"); // 指定IP地址
multicastSocket = new MulticastSocket(port); // 指定端口
multicastSocket.joinGroup(ipAddress); // 将IP地址加入广播组
} catch (Exception e) {
e.printStackTrace();
}
setBounds(100, 50, 360, 380);
setVisible(true);
}
/**
* 该方法不能显示调用,调用start()时会自动调用
*/
public void run() {
while(true) {
byte data[] = new byte[1024];
DatagramPacket packet = null;
// 待接收到的数据打包
packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
multicastSocket.receive(packet); // 接收数据包
String message = new String(packet.getData(), 0, packet.getLength());
inceAr.setText("正在接收的内容:\n" + message);
inced.append(message + "\n");
} catch (Exception e) {
e.printStackTrace();
}
if (b == true) break; // 退出循环
}
}
/**
* 单击事件,该函数不能显示调用,单击按钮时会自动调用
*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ince) {
ince.setBackground(Color.red);
stop.setBackground(Color.yellow);
if (!(thread.isAlive())) { // 如果线程不是新建状态则新建一个线程
thread = new Thread(this);
}
thread.start(); // 启动线程,run()会被自动调用
b = false;
}
if (e.getSource() == stop) {
ince.setBackground(Color.yellow);
stop.setBackground(Color.red);
b = true;
}
}
public static void main(String[] args) {
UdpClient udp = new UdpClient();
udp.setSize(460, 200);
}
}
```
```
打开第一个cmd窗口执行服务端程序:
编译源码:javac TcpServer.java -encoding utf-8
执行程序:java net.server.TcpServer
打开第二个cmd窗口执行客户端程序:
编译源码:javac TcpClient.java -encoding utf-8
执行程序:java net.client.TcpClient
打开第三个cmd窗口执行客户端程序:
编译源码:javac TcpClient.java -encoding utf-8
执行程序:java net.client.TcpClient
```
效果如下:
![](https://img.kancloud.cn/1a/29/1a29afd84e6768ecec69a527cb571100_1313x397.png)
- 网络通信
- 网络协议
- 端口和套接字
- TCP网络程序
- UDP网络程序
- 多线程聊天室
- 多线程
- 线程相关概念
- 线程实现方式
- 中断线程
- 线程生命周期
- 线程优先级
- 优先级规则
- 案例演示
- 线程同步机制
- 线程同步机制
- synchronized关键字
- ReentrantLock类
- Condition类
- 监视器概念
- volatile关键字
- final变量
- 死锁
- 线程局部变量
- 读/写锁
- 原子类
- 阻塞队列
- 工作规则
- 案例演示
- 常用阻塞队列
- 线程安全集合
- 高效的映射/集/队列
- 并发集视图
- 写数组的拷贝
- Arrays类的并行数组算法
- 同步包装器
- Callable与Future
- 执行器
- 线程池
- 预定执行
- 控制任务组
- Fork-Join框架
- 同步器
- 同步器
- 信号量
- CountDownLatch类
- CyclicBarrier类
- Exchanger类
- SynchronousQueue类
- 线程与Swing
- Swing与线程问题
- 两个原则
- Swing工作线程
- 单一线程规则
- 文件IO
- File类
- 文件输入输出
- ZIP压缩文件
- 集合
- 集合框架
- 集合接口
- 集合实现类
- 线程安全集合
- 集合算法
- 迭代器
- 集合排序
- JDBC
- JDBC是什么
- JDBC-ODBC桥
- JDBC驱动程序类型
- JDBC常用类与接口
- 数据库操作
- 连接数据库
- 增/删/改/查/预处理
- 事务
- 批处理
- commons-dbutils工具
- 安全问题
- Jedis
- 使用Jedis操作Redis数据库
- JSON转换
- 使用连接池
- 案例
- 单例破坏
- 单例定义
- 单例实现方式
- 懒汉式实现单例
- 饿汉式实现单例
- 单例破坏
- 类的单例破坏
- 枚举的单例破坏
- 克隆
- 克隆是什么
- 浅克隆
- 深克隆
- 注解
- 注解是什么
- 三大注解
- 内置注解
- 元注解
- 自定义注解
- NIO
- 相关概念
- BIO/NIO/AIO
- 多线程编程
- 线程同步
- 线程通信
- NIO
- NIO三大核心组件
- NIO网络编程
- NIO文件读写
- AIO
- Java8新特性
- Lambda表达式
- 方法引用
- 函数式接口
- 默认方法
- 什么是默认方法
- 默认方法语法格式
- 多个同名的默认方法问题
- 静态默认方法
- 默认方法实例
- Stream
- Stream是什么
- Stream示例
- Optional容器
- 新的日期时间API
- Base64
- SPI
- SPI是什么
- SPI与API的区别
- 常见场景
- 使用SPI需遵循的约定
- SPI使用步骤