1 UDP的定义
UDP
(User Datagram Protocol)是一个无连接
的传输层协议,提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据。UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差
。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小
、数据传输效率高
,适合对可靠性要求不高的应用程序。
2 报文传输模拟动态图
有需要查看TCP面向连接实现双人聊天的小伙伴,可直接点击<IT_WEH_coder>的博文[网络编程(利用TCP实现简单的双人聊天)链接]
3 主要应用
(1)适用场合
音频、视频和普通数据在传送时使用UDP,比如我们聊天用的QQ就是使用的UDP协议。
(2)实际应用
应用于现场测控领域,面向的是分布化的控制器、监测器等。在现场通信中,若某一应用要将一组数据传送给网络中的另一个节点,可由UDP进程将数据加上报头后传送给IP进程,UDP协议省去了建立连接和拆除连接的过程,取消了重发检验机制,能够达到较高的通信速率。
4 实例代码
客户端1号代码:
package com.weh.demo05;
//UDP实现双人聊天:客户端1号
public class TestClient01 {
public static void main(String[] args) {
// 开启线程
new Thread(new UDPSender(1111,"localhost",2222)).start();
new Thread(new UDPReceiver(3333,"TestClient02")).start();
}
}
客户端2号代码:
package com.weh.demo05;
//UDP实现双人聊天:客户端2号
public class TestClient02 {
public static void main(String[] args) {
// 开启线程
new Thread(new UDPSender(4444,"localhost",3333)).start();
new Thread(new UDPReceiver(2222,"TestClient01")).start();
}
}
发送端代码:
package com.weh.demo05;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
//发送端
public class UDPSender implements Runnable{
// 初始化
DatagramSocket socket = null; //创建DatagramSocket对象
BufferedReader reader = null;//创建BufferedReader对象
private int localPort;//本地端口号
private final String localIP;//本地IP
private final int sendPort;//发送端口号
//构造方法,传入本地端口、本地ip,发送端口
public UDPSender(int localPort, String localIP, int sendPort) {
this.localPort = localPort;
this.localIP = localIP;
this.sendPort = sendPort;
try {
socket = new DatagramSocket(localPort);//发送数据初始化,监听localPort本地端口的报文
reader = new BufferedReader(new InputStreamReader((System.in)));// 读取用户输入的数据
} catch (SocketException e) {
e.printStackTrace();
}
}
//重写run方法,执行发送消息的发包和打包过程
@Override
public void run() {
while (true) {
try {
/*
readLine()方法在进行读取一行时,
只有遇到回车(\r)或者换行符(\n)才会返回读取结果
*/
String dataline = reader.readLine();
// 需要准备数据发送包,将字符串转换为字节
byte[] datapacket = dataline.getBytes(StandardCharsets.UTF_8);
/*
创建一个用于发送的DatagramPacket对象
,指定发送datas数组中从offset开始,
总共datapacket.length个字节。
*/
DatagramPacket packet = new DatagramPacket(datapacket,0,datapacket.length,new InetSocketAddress(this.localIP,this.sendPort));
// send()方法根据数据包的目的地址来寻径以传送数据报
socket.send(packet);
if (dataline.equals("End!")) {
break; //跳出while循环,结束发送端
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭套接字,结束发送端的程序执行操作
socket.close();
}
}
接收端代码:
package com.weh.demo05;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDPReceiver implements Runnable{
// 初始化
DatagramSocket socket = null;//创建DatagramSocket对象
private int receiverPort;//接收端的端口号
private final String receiver;//接收者
// 构造方法
public UDPReceiver(int receiverPort, String receiver) {
this.receiverPort = receiverPort;
this.receiver = receiver;
try {
// 监听receivePort端口的报文
socket = new DatagramSocket(receiverPort);
} catch (SocketException e) {
e.printStackTrace();
}
}
//负责接收信息
@Override
public void run() {
boolean flag = true;
while (true) {
try {
byte[] database = new byte[1024];
/*
创建一个用于接收信息的DatagramPacket对象
,指定接收database数组中从offset开始,
总共database.length个字节的数据。
*/
DatagramPacket packet = new DatagramPacket(database,0,database.length);
// 等待(该方法会阻塞调用该方法的线程)接收数据包,直到收到一个数据包为止
socket.receive(packet);
if (flag){
System.out.println("\033[1;93;45m" + "对方在线中"+"\033[m");//控制台输出颜色字体
flag=false;
}
// 将字节流转化为字符流
String Data = new String(packet.getData(),0,packet.getLength());
if (Data.equals("End!")) {
System.err.println("对方已离线");
break;//退出while循环
}else {
System.out.println("\033[1;94m" +receiver+":"+Data);//输出收到的信息
}
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();//关闭套接字,结束接收端的执行操作
}
}
5 效果展示
博主后记:
希望看到此篇博文的网友,如果发现有什么不对的地方,欢迎在下方留言指正!博主一定虚心接受并改正!大家一起共同进步。如果对你有所帮助,可以给博主一个赞👍。