java网络编程之udp协议
UDP: User Datagram Protocol. 用户数据报协议。
一种无连接的 传输层协议,提供面向事务的简单不可靠信息传送服务 。
特点:
速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据。
没有服务端,只有发送端和接收端
单播 - 单台主机与单台主机之间的通信
单播只能是发送方往接收方指定的IP和端口发送数据
在IPv4网络中,0.0.0.0到223.255.255.255属于单播地址
注意:
- 单播很简单,就是一对一,所以ip地址和端口号一致即可。
- 发送方无需设置端口号,主要设置接收方的端口号
发送端
public class UDPSend {
public static void main(String [] args) throws IOException {
System.out.println("发送端启动");
//1 创建一个发送端的socker对象-找码头。无需端口号
DatagramSocket socket = new DatagramSocket();
//2 创建发送的数据包-打包礼物
byte [] bytes = "Hello UDP!".getBytes();
// 参数说明:发送消息的字节数组,发送消息的偏移量,发送消息的长度,地址,端口
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,InetAddress.getByName("127.0.0.1"),2000);
//3 发送数据-由码头发送包裹
socket.send(packet);
//4 关闭发送端-付钱走羊
socket.close();
System.out.println("发送端退出");
}
}
接收端
public class UDPReceive {
public static void main(String [] args) throws IOException {
System.out.println("接收消息端启动.....");
//1. 创建接收端socker-找码头, 这个端口号一定要和发送端的DatagramPacket对象里的端口号一样。
DatagramSocket datagramSocket = new DatagramSocket(2000);
//2. 创建接收数据的数据包-找新箱子
byte [] bytes = new byte[1024];
// 参数说明接收消息的字节数组,接收消息的长度,地址,端口,这里的端口号在单播时不重要。
DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
//3. 接收数据-码头接收礼物并放入新箱子中
datagramSocket.receive(packet);
//4. 解包数据,变成字符串输出-村长从箱子里获取礼物
String content = new String(packet.getData(),0,packet.getLength());
System.out.println("收到消息:" + content);
//4. 关闭连接-拿完走羊
System.out.println("接收端退出");
}
}
组播- 当前主机与选定的一组主机的通信
单播是一对一的发送,组播就是一对多的发送,但组播是有地址段要求的。
ipv4中的组播地址范围是:224.0.0.0到239.255.255.255
224.0.0.0~224.0.0.255 为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255 是公用组播地址,可以用于Internet;欲使用需申请。
224.0.2.0~238.255.255.255 为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255 为本地管理组播地址,仅在特定的本地范围内有效。
组播需具备的条件:
- 接收方设置组播属性及组播号
- 发送方往接收方定义的组播地址发送
- 接收方和发送方端口号需要一致
注意:
- 组播使用的是MulticastSocket
- 组播地址只能是224.0.0.0到239.255.255.255
- 组播作为接收方,需要使用joinGroup加入到对应的组播地址
- 一个机子上可以有多个接收端(不会报端口占用异常)
组播发送端
public class UDPMulticastSend {
public static void main(String [] args) throws IOException {
System.out.println("组播发送端启动");
//1. 创建接收端socket
DatagramSocket ds = new DatagramSocket();
String s = "hello 组播消息";
byte[] bytes = s.getBytes();
//2. 组播地址
InetAddress address = InetAddress.getByName("224.0.2.0");
// 接收方端口
int port = 10000;
//3. 创建消息数据包
DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//4. 进行组播消息发送
ds.send(dp);
ds.close();
}
}
组播接收端
public class UDPMulticastReceive {
public static void main(String [] args) throws IOException {
String id = UUID.randomUUID().toString();
System.out.println(id + "组播接收端启动..");
//1 创建组播socket,这里和单播是不一样的。
MulticastSocket multicastSocket = new MulticastSocket(10000);
// 2 创建接收的数据包
DatagramPacket datagramPacket = new DatagramPacket(new byte[1024],1024);
//3! 把当前计算机绑定一个组播地址,表示添加到这一组中.
multicastSocket.joinGroup(InetAddress.getByName("224.0.2.0"));
//4 接收消息包
multicastSocket.receive(datagramPacket);
String message = new String(datagramPacket.getData(),0,datagramPacket.getLength());
System.out.println(new String("收到消息:" + message));
}
}
public class UDPMulticastReceive2 {
public static void main(String [] args) throws IOException {
String id = UUID.randomUUID().toString();
System.out.println(id + "组播接收端启动..");
//端口要和发送方端口一一致
int port = 10000;
//1 创建组播socket,这里和单播是不一样的。
MulticastSocket multicastSocket = new MulticastSocket(port);
// 2 创建接收的数据包
DatagramPacket datagramPacket = new DatagramPacket(new byte[1024],1024);
//3 把当前计算机绑定一个组播地址,表示添加到这一组中,这也是设置组播地址 满足前面是224
multicastSocket.joinGroup(InetAddress.getByName("224.0.2.0"));
//4 接收消息包
multicastSocket.receive(datagramPacket);
String message = new String(datagramPacket.getData(),0,datagramPacket.getLength());
System.out.println(new String("收到消息:" + message));
}
}
广播- 当前主机与网络中的所有主机通信
使用广播地址:255.255.255.255
另外ipv6不支持广播
注意:
- 广播地址为255.255.255.255
- 广播是限制在局域网中的,只要是局域网内的机子都能收到消息(和单播的区别)
- ipv6没有广播地址
- 发送方设置要接收数据的地址
- 不能在一个机子上有两个接受程序,因为端口号被占用了。
- 接收方无需设置地址,这一点和单播很像
广播发送端
public class UDPBroadcastSend {
public static void main(String [] args) throws IOException {
System.out.println("广播发送端启动");
//1 创建发送端socket
DatagramSocket datagramSocket = new DatagramSocket();
String s = "广播 hello";
byte[] bytes = s.getBytes();
// 这里和单播唯一不同的是地址不同。广播地址是255.255.255.255,不能是其它地址
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 10000;
// 创建发送的数据包
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length,address,port);
//发送数据
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}
广播接收端
public class UDPBroadcastSend {
public static void main(String [] args) throws IOException {
System.out.println("广播发送端启动");
//1 创建发送端socket
DatagramSocket datagramSocket = new DatagramSocket();
String s = "广播 hello";
byte[] bytes = s.getBytes();
// 这里和单播唯一不同的是地址不同。广播地址是255.255.255.255,不能是其它地址
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 10000;
// 创建发送的数据包
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length,address,port);
//发送数据
datagramSocket.send(datagramPacket);
datagramSocket.close();
}
}