前言:UDP是一种无连接的传输层协议,数据以报文形式传播,单次最大数据量为64KB(减去头部信息后实际更小)。UDP通信方式主要有三种:单播、组播和广播
本文将结合Java代码,详细介绍这三种UDP通信方式的实现方法。
1. UDP基础知识
-
单播:一对一通信,发送端向指定IP和端口发送数据。
-
组播:一对多通信,发送端向一个组播组地址发送数据,组内所有成员都能接收。
-
广播:一对所有通信,发送端向局域网内所有主机广播数据。
UDP以报文形式传播信息,一次传播的信息最大为64KB,再减去头文件等信息,实际大小要小于64KB
UDP的传播方式主要分单播 组播 广播三种形式
单播为一对一的关系
组播为一对多的关系
广播为一对所有,对局域网内所有的电脑这个端口处均发送一次信息
2. 单播,如何实现?
分发送端与接收端。
发送端需要确定目标地址,目标端口,以及要传播的数据,如下
package udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class SendMessage {
public static void main(String[] args) throws Exception {
//会绑定端口,去与外部的端口具体的链接
//可以写也可以不写,随机端口
DatagramSocket ds=new DatagramSocket();
Scanner sc=new Scanner(System.in);
//打包数据,这个数据的相关发送信息什么的
String str;
str=sc.next();
while (!str.equals("886"))
{
byte[] bytes = str.getBytes();
InetAddress byAddress = InetAddress.getByName("127.0.0.1");
int port=10086;
DatagramPacket dp=new DatagramPacket(bytes,bytes.length,byAddress,port);
ds.send(dp);
str=sc.next();
}
ds.close();
}
}
发出去了,接收端怎么接受?端口要照,然后用数据包进行接收。只不过,如何打印出来数据呢?观察传播的数据类型就知道传播的是字节数组,把它进行字符串的转换即可
package udp;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveMessage {
public static void main(String[] args) throws Exception{
DatagramSocket ds=new DatagramSocket(10086);
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
while (true){
ds.receive(dp);
byte[] A= dp.getData();
int len=dp.getLength();
System.out.println("该数据从"+dp.getAddress()+"端口:"+dp.getPort());
System.out.println("接受到数据:"+new String(A,0,len));
}
//ds.close();
}
}
3. 组播,如何实现?
组播的地址范围为224.0.0.0-239.255.255.255
这里面不是使用DatagramSocker了用的是MulticastSocket,同时绑定IP是通过join的方式绑定
发送端代码如下
package udp_many;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.util.Scanner;
public class SendMessage {
//组播地址:224.0.0.0 ~ 239.255.255.255
public static void main(String[] args) throws Exception {
//会绑定端口,去与外部的端口具体的链接
//可以写也可以不写,随机端口
MulticastSocket ds=new MulticastSocket();
Scanner sc=new Scanner(System.in);
//打包数据,这个数据的相关发送信息什么的
String str;
str=sc.next();
byte[] bytes = str.getBytes();
InetAddress byAddress = InetAddress.getByName("224.0.0.1");
int port=10000;
DatagramPacket dp=new DatagramPacket(bytes,bytes.length,byAddress,port);
ds.send(dp);
str=sc.next();
ds.close();
}
}
接收端代码如下
package udp_many;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class ReceiveMessage{
public static void main(String[] args) throws Exception{
//这里面接收端可以是多个,多个接收端接受多个发送端发送的信息
MulticastSocket ds=new MulticastSocket(10000);
InetAddress address=InetAddress.getByName("224.0.0.1");
ds.joinGroup(address);
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
byte[] A= dp.getData();
int len=dp.getLength();
String name=dp.getAddress().getHostName();
System.out.println("该数据从"+name+" "+dp.getAddress()+"端口:"+dp.getPort());
System.out.println("接受到数据:"+new String(A,0,len));
//ds.close();
}
}
4. 广播如何实现?
广播与单播基本代码相似,只不过发送端绑定的目的IP不同
广播的IP主要为255.255.255.255,只不过,这个IP设置的前提为局域网下的所有电脑均处于同一网关下,下方这个图IPv4地址与网关地址不同,那么,电脑B与我们处于同一网关下,但是IPv4的网段不同即IPv4前三位不是10.9.23时,我们的255.255.255.255是不起作用的,这时候我们需要设置地址为10.9.63.255。
这样即使默认网关相同,但IPv4的网段不同,目的电脑也能收到
如果IPv4地址与默认网关的前三位相同,那么255.255.255.255起作用,同一局域网下的电脑可以接收到信息ok,代码如下
发送端
package udp_all;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
public class BroadcastSender {
public static void main(String[] args) throws Exception {
// 电脑1(发送端) 电脑2
//IPv4地址 10.9.23.62 10.9.34.244
//子网掩码 255.255.192.0 255.255.192.0
//默认网关 10.9.63.254 10.9.63.254
//发送端电脑一
//发送端绑定10.9.23.255时,两台电脑均无法接收到代码
//发送端绑定255.255.255.255时,电脑一可以收到信息,电脑二收不到信息
//发送端绑定10.9.63.255时,两台电脑均可以收到信息,只不过电脑二接收两遍
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true); // 允许广播
Scanner scanner = new Scanner(System.in);
System.out.println("输入消息,输入886退出:");
while (true) {
String message = scanner.nextLine();
if ("886".equals(message)) break;
byte[] data = message.getBytes();
// 替换为你所在局域网的广播地址,例如192.168.1.255
InetAddress broadcastAddress = InetAddress.getByName("10.9.63.255");
int port = 8888;
DatagramPacket packet = new DatagramPacket(data, data.length, broadcastAddress, port);
socket.send(packet);
System.out.println("广播消息已发送:" + message);
}
socket.close();
scanner.close();
}
}
接收端
package udp_all;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class Receive_all {
public static void main(String[] args) throws Exception {
int port = 8888;
DatagramSocket socket = new DatagramSocket(port);
System.out.println("Receiver started, waiting for broadcast messages...");
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
socket.receive(packet);
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println("Received: " + msg);
}
}
}
5. 总结与建议
-
UDP适合对实时性要求高但允许丢包的应用,如视频直播、在线游戏。
-
代码示例均添加了异常处理,方便调试和运行。
如果你觉得本文对你有帮助,欢迎点赞、收藏和关注!
也欢迎留言交流UDP网络编程的更多问题。