UDP 是无连接的数据报服务,不对数据报进行检查与修改,无须等待对方的应答,速度快,可能会丢包,UDP段结构比TCP的段结构简单,因此网络开销也小。
UDP数据报格式有 首部 和数据 两个部分
首部 为8个字节 包括以下部分
(1) 源端口:源端口号,2个字节,最大值为65525
(2)目的端口:目的端口号,2个字节,最大值为65525
(3)长度:2字节,UDP用户数据报的总长度
(4)校验和:2字节,用于校验UDP数据报的数字段和包含UDP数据报首部的“伪首部”
“伪首部” :伪包头
(1)UDP传送数据前并不与对方建立连接,即UDP是无连接的,在传输数据前,发送方和接收方相到交换信息使双方同步
(2)UDP对接收的数据报不发送确认信号,发送端不知道 数据是否被正确接收,也不会重发数据
(3)UDP传送数据比TCP 快速,系统弄错也少。
①开销更小
TCP为了保证其可靠性,首部包含20字节,以及40字节的可选项,UDP首部只有8字节
②速度更快
1 UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。
2 TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。
3 与TCP不同,UDP协议并不提供数据传送的保证机制。
1 UDP服务端开发启动类 UDPServer
package com.UDP;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
public class UDPServer {
public void run(int port)throws Exception{
EventLoopGroup bossGroup=new NioEventLoopGroup();
try
{
//通过NioDatagramChannel创建Channel,并设置Socket参数支持广播
//UDP相对于TCP不需要在客户端和服务端建立实际的连接,因此不需要为连接(ChannelPipeline)设置handler
Bootstrap b=new Bootstrap();
b.group(bossGroup)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPServerHandler());
b.bind(port).sync().channel().closeFuture().await();
}
catch (Exception e)
{
e.printStackTrace();
}
finally{
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args)throws Exception
{
new UDPServer().run(8089);
}
}
2 UDP服务端开发辅助处理类 UDPServerHandler
package com.UDP;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
public class UDPServerHandler extends
SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
//利用ByteBuf的toString()方法获取请求消息
String req=packet.content().toString(CharsetUtil.UTF_8);
System.out.println(req);
if("结果".equals(req)) {
ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(
"结果" + "Netty UDP", CharsetUtil.UTF_8), packet.sender()));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause)
throws Exception{
ctx.close();
cause.printStackTrace();
}
}
3 UDP客户端开发启动类
package com.UDP;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.Channel;
import io.netty.util.CharsetUtil;
import io.netty.channel.socket.DatagramPacket;
import java.net.InetSocketAddress;
public class UDPClient {
public void connect(int port) {
// 配置nio线程组
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPClientHandler());
Channel ch = bootstrap.bind(0).sync().channel();
ch.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(
"结果", CharsetUtil.UTF_8), new InetSocketAddress(
"255.255.255.255", port))).sync();
if(!ch.closeFuture().await(15000)){
System.out.println("查询超时!!!");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("出错了");
} finally {
group.shutdownGracefully();
}
}
public static void main(String[] args) {
new UDPClient().connect(8089);
}
}
4 UDP客户端开发辅助处理类
package com.UDP;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
public class UDPClientHandler extends
SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
String response=msg.content().toString(CharsetUtil.UTF_8);
if(response.startsWith("结果")){
System.out.println(response);
ctx.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable
cause)throws Exception{
cause.printStackTrace();
ctx.close();
}
}
5结果:
15:29:12.151 [main] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
15:29:12.151 [main] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
15:29:12.154 [main] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@3712b94
15:29:12.160 [main] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
15:29:12.160 [main] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
15:29:12.160 [main] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
15:29:12.160 [main] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
结果Netty UDP
注解:
DatagramChannel:
Java NIO中的DatagramChannel定义在java.nio.channels包中,是一个能收发UDP包的通道。