今天有人问我Netty的UDP怎么使用,我自己尝试的去写一个Demo,在网上搜索了一下,关于Netty的UDP实现还是很少的,所以,今天写下这篇文章用来记录今天的一个简单Demo实现
不使用Netty的UDP实例:
UdpServer.java
packagecom.rainy.netty.udp02;importjava.io.IOException;importjava.net.DatagramPacket;importjava.net.DatagramSocket;/*** Created by smzdm on 16/8/10.*/
public classUdpServer {public static final int PORT = 30000;//定义每个数据报的最大大小为4KB
private static final int DATA_LEN = 4096;//定义接收网络数据的字节数组
byte[] inBuff = new byte[DATA_LEN];//以指定字节数组创建准备接收数据的DatagramPacket对象
private DatagramPacket inPacket =
newDatagramPacket(inBuff, inBuff.length);//定义一个用于发送的DatagramPacket对象
privateDatagramPacket outPacket;//定义一个字符串数组,服务器端发送该数组的元素
String[] books = newString[] {"疯狂Java讲义","轻量级Java EE企业应用实战","疯狂Android讲义","疯狂Ajax讲义"};public void init() throwsIOException {try{//创建DatagramSocket对象
DatagramSocket socket = newDatagramSocket(PORT);//采用循环接收数据
for (int i = 0; i < 1000; i++) {//读取Socket中的数据,读到的数据放入inPacket封装的数组里
socket.receive(inPacket);//判断inPacket.getData()和inBuff是否是同一个数组
System.out.println(inBuff ==inPacket.getData());//将接收到的内容转换成字符串后输出
System.out.println(newString(inBuff
,0, inPacket.getLength()));//从字符串数组中取出一个元素作为发送数据
byte[] sendData = books[i % 4].getBytes();//以指定的字节数组作为发送数据,以刚接收到的DatagramPacket的//源SocketAddress作为目标SocketAddress创建DatagramPacket
outPacket = newDatagramPacket(sendData
, sendData.length, inPacket.getSocketAddress());//发送数据
socket.send(outPacket);
}
}catch(Exception e) {
System.out.println(e.getMessage());
}
}public static void main(String[] args) throwsIOException {newUdpServer().init();
}
}
UdpClient.java
packagecom.rainy.netty.udp02;importjava.io.IOException;importjava.net.DatagramPacket;importjava.net.DatagramSocket;importjava.net.InetAddress;importjava.util.Scanner;/*** Created by smzdm on 16/8/10.*/
public classUdpClient {//定义发送数据报的目的地
public static final int DEST_PORT = 30000;public static final String DEST_IP = "127.0.0.1";//定义每个数据报的最大大小为4KB
private static final int DATA_LEN = 4096;//定义接收网络数据的字节数组
byte[] inBuff = new byte[DATA_LEN];//以指定的字节数组创建准备接收数据的DatagramPacket对象
private DatagramPacket inPacket =
newDatagramPacket(inBuff, inBuff.length);//定义一个用于发送的DatagramPacket对象
private DatagramPacket outPacket = null;public void init() throwsIOException {try{//创建一个客户端DatagramSocket,使用随机端口
DatagramSocket socket = newDatagramSocket();//初始化发送用的DatagramSocket,它包含一个长度为0的字节数组
outPacket = new DatagramPacket(new byte[0], 0, InetAddress.getByName(DEST_IP), DEST_PORT);//创建键盘输入流
Scanner scan = newScanner(System.in);//不断地读取键盘输入
while(scan.hasNextLine()) {//将键盘输入的一行字符串转换成字节数组
byte[] buff =scan.nextLine().getBytes();//设置发送用的DatagramPacket中的字节数据
outPacket.setData(buff);//发送数据报
socket.send(outPacket);//读取Socket中的数据,读到的数据放在inPacket所封装的字节数组中
socket.receive(inPacket);
System.out.println(new String(inBuff, 0, inPacket.getLength()));
}
}catch(Exception e) {
System.out.println(e.getMessage());
}
}public static void main(String[] args) throwsIOException {newUdpClient().init();
}
}
这两段代码是在网上搜罗的例子,
原文路径:http://blog.csdn.net/jiangxinyu/article/details/8161044
在这个例子中,我们可以看到,UDP的实现方式和TCP的实现方式上是不同的,UDP的实现在于,发送数据包,后面我也在网上查看了一些问题,关于粘包问题,我发现,网上部分说UDP有粘包问题,部分说没有UDP粘包问题,就算有也是很少量的不容易出现的问题,其实,我偏向于UDP没有粘包问题,因为UDP本身是按包发送,而且,UDP和TCP不一样,UDP是包完整就发送,而TCP在包完整的情况下,会判断是否值得发送,有发送缓存的实现,所以,综合分析,我觉得UDP应该是不存在粘包问题,拆包问题同样就没有了。
Netty实现UDP的案例,
NettyUdpServer.java
package com.rainy.netty.udp01;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
/**
* Created by smzdm on 16/8/10.
*/
public class NettyUdpServer {
public static void main(String[] args) throws InterruptedException {
Bootstrap b = new Bootstrap();
EventLoopGroup group = new NioEventLoopGroup();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPSeverHandler());
b.bind(9000).sync().channel().closeFuture().await();
}
}
class UDPSeverHandler extends SimpleChannelInboundHandler {
@Override
protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
ByteBuf buf = (ByteBuf) packet.copy().content();
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println(body);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
super.channelRegistered(ctx);
System.out.println("I got it!");
}
}
NettyUdpClient.java
packagecom.rainy.netty.udp;importjava.net.InetSocketAddress;importio.netty.bootstrap.Bootstrap;importio.netty.buffer.Unpooled;importio.netty.channel.Channel;importio.netty.channel.ChannelHandlerContext;importio.netty.channel.ChannelOption;importio.netty.channel.EventLoopGroup;importio.netty.channel.SimpleChannelInboundHandler;importio.netty.channel.nio.NioEventLoopGroup;importio.netty.channel.socket.DatagramPacket;importio.netty.channel.socket.nio.NioDatagramChannel;importio.netty.util.CharsetUtil;/*** Created by smzdm on 16/8/10.*/
public classNettyUdpClient {public static voidmain(String[] args) {
EventLoopGroup group= newNioEventLoopGroup();try{
Bootstrap b= newBootstrap();
b.group(group).channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST,true)
.handler(newUdpClientHandler());
Channel ch= b.bind(0).sync().channel();//向网段类所有机器广播发UDP
ch.writeAndFlush(newDatagramPacket(
Unpooled.copiedBuffer("发送第一个UDP", CharsetUtil.UTF_8),new InetSocketAddress("127.0.0.1", 9000))).sync();if(!ch.closeFuture().await(15000)){
System.out.println("查询超时!!!");
}
}catch(Exception e) {
System.out.println(e.getMessage());
}finally{
group.shutdownGracefully();
}
}
}class UdpClientHandler extends SimpleChannelInboundHandler{
@Overridepublic voidmessageReceived(ChannelHandlerContext channelHandlerContext,
DatagramPacket datagramPacket)throwsException {
String response=datagramPacket.content().toString(CharsetUtil.UTF_8);if(response.startsWith("结果:")){
System.out.println(response);
channelHandlerContext.close();
}
}
@Overridepublic void exceptionCaught(ChannelHandlerContext ctx,Throwable cause)throwsException{
ctx.close();
cause.printStackTrace();
}
}
netty对应原文路径:http://www.tuicool.com/articles/Rry6biF
上面的例子作为参考进行的代码处理,发现这样就能使得代码正常发送,如果你需要获取对应的发送端的IP地址,那么,你可以使用
packet.sender().getAddress().getHostAddress();
进行获取发送端IP地址,本质上来说,这个UDP一般都是基于使用UDP的方式进行自定义协议方式实现业务功能,具体可以根据自己的文档格式进行对应的解析。这个方式,如果做过银行接口的,应该对这个接口实现方式有一定的认识。
本文暂时先写到这里,如果有什么问题,请留言。大家一起交流讨论NIO方面的问题,一起进步。