android平台下利用Netty实现UDP通信

4,520 阅读1分钟

客户端、服务端都依赖netty-all-4.0.23.Final.jar

UDP客户端

public class UdpClient extends UdpChannelInboundHandler implements Runnable{
    private Bootstrap bootstrap;
    private EventLoopGroup eventLoopGroup;
    private UdpChannelInitializer udpChannelInitializer;
    private ExecutorService executorService;

    public UdpClient(){
        init();
    }

    private void init(){
        bootstrap = new Bootstrap();
        eventLoopGroup = new NioEventLoopGroup();
        bootstrap.group(eventLoopGroup);
        bootstrap.channel(NioDatagramChannel.class)
                .option(ChannelOption.SO_RCVBUF,1024)
                .option(ChannelOption.SO_SNDBUF,1024);
        udpChannelInitializer = new UdpChannelInitializer(this);
        bootstrap.handler(udpChannelInitializer);

        executorService = Executors.newSingleThreadExecutor();
        executorService.execute(this);
    }

    @Override
    public void run() {
        try {
            ChannelFuture channelFuture = bootstrap.bind(0).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

    public void send(){
        send(new DatagramPacket(Unpooled.copiedBuffer("echo", CharsetUtil.UTF_8),new InetSocketAddress("127.0.0.1",1112)));
    }

    @Override
    public void receive(String data) {
        Log.d("nettyudp","receive" + data);
    }
}
public class UdpChannelInitializer extends ChannelInitializer<DatagramChannel> {
    private UdpChannelInboundHandler inboundHandler;
    public UdpChannelInitializer(UdpChannelInboundHandler handler){
        inboundHandler = handler;
    }

    @Override
    protected void initChannel(DatagramChannel datagramChannel) throws Exception {
        ChannelPipeline pipeline = datagramChannel.pipeline();
        pipeline.addLast(new IdleStateHandler(12,15,0));
        pipeline.addLast(inboundHandler);
    }
}
public abstract class UdpChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    private ChannelHandlerContext handlerContext;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        handlerContext = ctx;
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        handlerContext.close();
    }

    public void send(Object o){
        handlerContext.writeAndFlush(o).addListener(new GenericFutureListener<ChannelFuture>() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                Log.d("nettyudp","operationComplete "+future.isSuccess());
            }
        });
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        String body = datagramPacket.content().toString(CharsetUtil.UTF_8);
        receive(body);
    }

    public abstract void receive(String data);
}

新建UdpClient实例启动客户端线程,接收到的消息通过抽象方法receive回调,void send()用来往服务器发送消息。

udpClient = new UdpClient();
udpClient.send();

UDP服务端

调用init启动服务端

public class Udpserver {
    public static void init() {
        new Thread(){
            @Override
            public void run() {
                try {
                    Bootstrap b = new Bootstrap();
                    EventLoopGroup group = new NioEventLoopGroup();
                    b.group(group)
                            .channel(NioDatagramChannel.class)
                            .option(ChannelOption.SO_BROADCAST, true)
                            .handler(new UdpServerHandler());
                    Log.d("nettyudp","server");
                    b.bind(1112).sync().channel().closeFuture().await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

    private static class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
            String body = packet.content().toString(CharsetUtil.UTF_8);
            Log.d("nettyudp","server>>"+body);
            
            DatagramPacket data = new DatagramPacket(Unpooled.copiedBuffer("echo from server", CharsetUtil.UTF_8), packet.sender());
            ctx.writeAndFlush(data);
        }
    }

}

或者

public class UdpServer {
    private final static int PORT = 1112;

    public static void init() {
    new Thread(){
        @Override
        public void run() {
            doJob();
        }
    }.start();
    }
	    public static void doJob() {
	        try (DatagramSocket socket = new DatagramSocket(PORT)) {
	            while (true) {
	                try {
	                    DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
	                    socket.receive(request);

	                    String daytime = new Date().toString();
	                    byte[] data = daytime.getBytes("ASCII");
	                    DatagramPacket response = new DatagramPacket(data, data.length, request.getAddress(), request.getPort());
	                    socket.send(response);
	                    Log.d("nettyudp",daytime + " " + request.getAddress());
	                } catch (IOException e) {
	                    e.printStackTrace();
	                }
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
	    }
}