先要说明的是udp本身是没有服务端和客户端之分的,但是为了好理解,下面例子暂且这么叫
1、应答端:
public class UdpAnswerSide {
public final static String ANSWER = "古诗来了:";
public void run(int port) throws Exception{
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();
}
}
public static void main(String [] args) throws Exception{
int port = 8080;
new UdpAnswerSide().run(port);
}
}
public class AnswerHandler extends
SimpleChannelInboundHandler<DatagramPacket> {
/*应答的具体内容从常量字符串数组中取得,由nextQuote方法随机获取*/
private static final String[] DICTIONARY = {
"只要功夫深,铁棒磨成针。",
"旧时王谢堂前燕,飞入寻常百姓家。",
"洛阳亲友如相问,一片冰心在玉壶。",
"一寸光阴一寸金,寸金难买寸光阴。",
"老骥伏枥,志在千里,烈士暮年,壮心不已" };
private static Random r = new Random();
private String nextQuote(){
return DICTIONARY[r.nextInt(DICTIONARY.length-1)];
}
@Override
protected void channelRead0(ChannelHandlerContext ctx,
DatagramPacket packet)
throws Exception {
//获得请求
String req = packet.content().toString(CharsetUtil.UTF_8);
System.out.println(req);
if(UdpQuestionSide.QUESTION.equals(req)){
/**
* 重新 new一个DatagramPacket对象,我们通过packet.sender()
* 来获取发送者的地址。
* 重新发送出去!
*/
ctx.writeAndFlush(
new DatagramPacket(
Unpooled.copiedBuffer(
UdpAnswerSide.ANSWER+nextQuote(),
CharsetUtil.UTF_8),
//可以看请求端此处new InetSocketAddress("127.0.0.1",port),而应答端可以直接从packet.sender())中获取这个属性,所以不用重新new了
packet.sender()));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
ctx.close();
cause.printStackTrace();
}
}
2、请求端
public class UdpQuestionSide {
public final static String QUESTION = "告诉我一句古诗";
public void run(int port) throws Exception{
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
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)
));
//不知道接收端能否收到报文,也不知道能否收到接收端的应答报文
// 所以等待15秒后,不再等待,关闭通信
if(!ch.closeFuture().await(15000)){
System.out.println("查询超时!");
}
} catch (Exception e) {
group.shutdownGracefully();
}
}
public static void main(String [] args) throws Exception{
int answerPort = 8080;
new UdpQuestionSide().run(answerPort);
}
}
public class QuestoinHandler extends
SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
throws Exception {
//获得应答,DatagramPacket提供了content()方法取得报文的实际内容
String response = msg.content().toString(CharsetUtil.UTF_8);
if (response.startsWith(UdpAnswerSide.ANSWER)) {
System.out.println(response);
ctx.close();
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
}