UDP: User Datagram Protocol 用户数据报协议 是一种无连接的协议。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。
使用UDP: 在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多
UDP广播:广播使用广播地址255.255.255.255,将消息发送到在同一广播网络上的每个主机。值得强调的是:本地广播信息是不会被路由器转发。当然这是十分容易理解的,因为如果路由器转发了广播信息,那么势必会引起网络瘫痪。这也是为什么IP协议的设计者故意没有定义互联网范围的广播机制。其实广播顾名思义,就是想局域网内所有的人说话,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。
发送接收 demo:
public static void sendBroadcast(byte[] data, int port) throws Exception{
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("255.255.255.255"), port);
socket.send(packet);
}
public static void receiveBoradcast(int port) {
new Thread(new Runnable() {
DatagramSocket socket;
@Override
public void run() {
while (true) {
try {
receive(port);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void receive(int port) throws Exception{
if (socket == null || socket.isClosed()) {
socket = new DatagramSocket(port);
socket.setBroadcast(true);
}
byte[] buffer = new byte[1024 * 100];
DatagramPacket packet = new DatagramPacket(buffer , buffer.length);
socket.receive(packet);
String data = new String(packet.getData(), 0, packet.getLength());
Log.i("receiver", data);
socket.close();
}
}).start();
}
Netty 实现 demo
public class Broadcast {
Channel udpChannel;
public void send(String data) throws Exception{
if(udpChannel != null) {
udpChannel.writeAndFlush(data);
}
}
public void init(int port) {
NioEventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new MessageToMessageEncoder<String>() {
@Override
protected void encode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception {
InetSocketAddress remoteAddress = new InetSocketAddress("255.255.255.255", port);
out.add(new DatagramPacket(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8), remoteAddress));
}
});
udpChannel = bootstrap.bind(0).syncUninterruptibly().channel();
}
}
public class BroadcastReceiver {
public void start(int port){
Bootstrap b = new Bootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
try {
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
String req = packet.content().toString(CharsetUtil.UTF_8);
System.out.println(req);
}
});
b.bind(port).sync().channel().closeFuture().await();
}catch (Exception e) {
e.printStackTrace();
}finally {
group.shutdownGracefully();
}
}
}
多播
多播数据报套接字类用于发送和接收 IP 多播包。MulticastSocket 是一种 (UDP) DatagramSocket,它具有加入 Internet 上其他多播主机的“组”的附加功能。
多播组通过 D 类 IP 地址和标准 UDP 端口号指定。D 类 IP 地址在 224.0.0.0 和 239.255.255.255 的范围内(包括两者)。地址 224.0.0.0 被保留,不应使用。
多播 demo
public class MultiBroadcast {
public void startReveive(String host, int port) {
new Thread(new Runnable() {
MulticastSocket ms;
private void receive(String host, int port) throws Exception{
byte[] buf = new byte[1024 * 100];
if(ms == null || ms.isClosed()) {
ms = new MulticastSocket(port);
DatagramPacket dp = new DatagramPacket(buf, buf.length);
InetAddress group = InetAddress.getByName(host);
ms.joinGroup(group);
ms.receive(dp);
}
Log.i("receiver", new String(buf));
ms.close();
}
@Override
public void run() {
while (true) {
try {
receive(host, port);
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
public void send(String host, int port, String message) throws Exception{
InetAddress group = InetAddress.getByName(host);
MulticastSocket s = new MulticastSocket();
s.joinGroup(group);
DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(), group,port);
s.send(dp);
s.close();
}
}
单播
public class UnicastBroadcast {
public void send(String host, int port, byte[] message) throws Exception{
//sending data to host and its port
InetAddress address = InetAddress.getByName(host);
// Initialize a datagram packet with data and address
DatagramPacket packet = new DatagramPacket(message, message.length, address, port);
// Create a datagram socket, send the packet through it, close it.
DatagramSocket dsocket = new DatagramSocket();
dsocket.send(packet);
dsocket.close();
}
public void startReceive() {
new Thread(new Runnable() {
DatagramSocket dsocket;
@Override
public void run() {
}
private void receive(int port) throws Exception{
byte[] buffer = new byte[2048];
if(dsocket == null || dsocket.isClosed()) {
//receiving data from its port
dsocket = new DatagramSocket(port);
// Create a buffer to read datagrams into. If a
// packet is larger than this buffer, the
// excess will simply be discarded!
// Create a packet to receive data into the buffer
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// Wait to receive a datagram
dsocket.receive(packet);
// Convert the contents to a string, and display them
String msg = new String(buffer);
System.out.println(packet.getAddress().getHostName() + ": " + msg);
}
dsocket.close();
}
}).start();
}
}
Netty dmo
http://colobu.com/2014/10/21/udp-and-unicast-multicast-broadcast-anycast/#单播