单播意味着点对点发送信息,要注意点为:
(1)连接协议规定为NioDatagramChannel协议。
(2)需要将UDP请求报文以DatagramPacket打包发送给接收端。
(3)由于UDP是不保证传输完整以及安全,或者正确,重点在意效率,不需要关注接收端是否有收到报文,所以接收端能否能收到数据,是依据接收是否有回复应答报文进行判断,所以设置等待时间进行接收(阻塞),等待时间过后关闭信道,不论是否有应答。
简单实现伪代码:
发送端:
b.group(group)
/*由于我们用的是UDP协议,所以要用NioDatagramChannel来创建*/
.channel(NioDatagramChannel.class)
.handler(new QuestoinHandler());
//不需要建立连接
Channel ch = b.bind(0).sync().channel();
//将UDP请求的报文以DatagramPacket打包发送给接受端
ch.writeAndFlush(
new DatagramPacket(
Unpooled.copiedBuffer(QUESTION,
CharsetUtil.UTF_8),
new InetSocketAddress("127.0.0.1",
port)))
.sync();
//不知道接收端能否收到报文,也不知道能否收到接收端的应答报文
// 所以等待15秒后,不再等待,关闭通信
if(!ch.closeFuture().await(15000)){
System.out.println("查询超时!");
}
应答端:
由于UDP无接受端这一说,没有建立连接,所以是发送端和接收端关系,是平等的。
EventLoopGroup group = new NioEventLoopGroup();
try {
/*和tcp的不同,udp没有接受连接的说法,所以即使是接收端,
也使用Bootstrap*/
Bootstrap b = new Bootstrap();
/*由于我们用的是UDP协议,所以要用NioDatagramChannel来创建*/
b.group(group)
.channel(NioDatagramChannel.class)
.handler(new AnswerHandler());
//没有接受客户端连接的过程,监听本地端口即可
ChannelFuture f = b.bind(port).sync();
System.out.println("应答服务已启动.....");
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
注意应答端消息处理类,由于是UDP通信,那么要进行应答回去,则需要源端口号进行通信,所以在回复消息时候需要调用packet.sender()进行获取源发送端口号,以便回复消息。
应答端处理部分代码:
//获得请求
String req = packet.content().toString(CharsetUtil.UTF_8);
if(UdpQuestionSide.QUESTION.equals(req)){ //进行校验请求信息是否为所能处理信息
String answer = UdpAnswerSide.ANSWER+nextQuote();
System.out.println("接收到请求:"+req);
//重新 new 一个DatagramPacket对象,我们通过packet.sender()来获取发送者的消息。重新发送出去!
ctx.writeAndFlush(
new DatagramPacket(
Unpooled.copiedBuffer(
answer,
CharsetUtil.UTF_8),
packet.sender())); //通过packet.sender()来获取发送者的消息,获取源端口号,然后发送回去消息。
}