Java nio Netty实现基本的收发包

Netty简介

netty是Java著名的nio库之一,以前是JBoss的项目,现在独立出来成为 io.netty。经测试Netty的性能比node.js更胜一筹,其内存和CPU占用率比其他的网络库低很多。Netty 4.x在3.x的基础上修改了一些接口,5.x版本在保持接口不变的情况下对内部架构作了一些优化。目前最新版是4.1和5.0同步更新。
为了学习nio,准备用netty实现一个端对端的收发packet的简单程序,服务器端与客户端之间互传任意长度的packet。
Packet的设计相当简单,直接用[len][content]构成,len为固定的2byte 16位,后面的content为长度为len的二进制流,其读写代码也很简单,直接用InputStream和OutputStream来处理输入和输出,可读写Socket,处理蓝牙数据流或tcp数据流:
public class Packet {

    public static final int MAX_LEN = 0xffff;

    public static class PacketInputStream {
        private final InputStream stream;
        private final byte[] twoBytes = new byte[2];

        public PacketInputStream(InputStream s) {
            stream = s;
        }

        public ByteBuffer readPacket() throws IOException {
            readBytes(twoBytes);
            int len = ((twoBytes[0] & 0xff) << 8) | twoBytes[1];
            byte[] buffer = new byte[len];
            return ByteBuffer.wrap(readBytes(buffer));
        }

        public byte[] readBytes(byte[] buffer) throws IOException {
            int bytes = 0;
            while (bytes < buffer.length) {
                int n = stream.read(buffer, bytes, buffer.length - bytes);
                if (n < 0) {
                    throw new IOException();
                }
                bytes += n;
            }
            return buffer;
        }

    }

    public static class PacketOutputStream {
        private OutputStream stream;

        public static ByteBuffer createPacket(int len) {
            return ByteBuffer.allocate(len).putShort((short) len);
        }

        public PacketOutputStream(OutputStream out) {
            stream = out;
        }

        public void writePacket(ByteBuffer buffer) throws IOException {
            writeByte(buffer.array());
        }

        public void writeByte(byte[] buffer) throws IOException{
            stream.write(buffer);
            stream.flush(); //确保整个包被一次性发出去
        }
    }
}

1. 根据EchoServer改的简单版

没耐心仔细读文档,先把example过一遍。
package com.company.nettytest;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;


/**
 * Created by fripside on 8/1/15.
 * http://my.oschina.net/flashsword/blog/162936
 */
public class NettyClient {

    public static void main(String[] args) {

        EventLoopGroup group = new NioEventLoopGroup(1);
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new ClientHandler());
                        }
                    });
            ChannelFuture f = b.connect("127.0.0.1", 8888).sync();
            f.channel().closeFuture().sync();
        } catch (Exception e) {

        } finally {
            group.shutdownGracefully();
        }
    }


    public void sendRandomPck() {

    }


}

class ReceivePackets {
    private BlockingQueue packets = new ArrayBlockingQueue<>(100);

}

class ClientHandler extends ChannelHandlerAdapter {
    private final ByteBuf firstMessage;
    private int times = 10;
    private final byte[] twoBytes = new byte[2];

    public ClientHandler() {
        firstMessage = Unpooled.buffer(256);
        firstMessage.writeShort(254);
        for (int i = 2; i < firstMessage.capacity(); ++i) {
            firstMessage.writeByte((byte) i);
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (times < 0) {
            ctx.close();
        }
        ByteBuf buf = (ByteBuf) msg;
        buf.readBytes(twoBytes);
        System.out.println("b1:" + twoBytes[0] + " b2:" + twoBytes[1]);
        int len = ((twoBytes[0]  << 8) & 0xff00) | (twoBytes[1] & 0xff);
        System.out.println("LEN: " + len + " Available:" + buf.readableBytes());
        byte[] all = new byte[len];

        buf.readBytes(all, 0, len);
        ctx.write(msg);
        System.out.println("Receive: " + times + " " + all);
        --times;
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}


package com.company.nettytest;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by fripside on 8/1/15.
 */
public class NettyServer {

    static Logger LOG = Logger.getGlobal();

    public static void main(String[] args) {
        LOG.setLevel(Level.INFO);
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 100)
                    .handler(new LoggingHandler())
                    .childHandler(new ChannelInitializer() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            LOG.info("client is connect....");
                            ChannelPipeline p = socketChannel.pipeline();
                            p.addLast(new ServerHandler());
                        }
                    });
            LOG.info("server is start....");
            ChannelFuture f = b.bind(8888).sync();
            f.channel().closeFuture().sync();
        } catch (Exception e) {

        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

class ServerHandler extends ChannelHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ctx.write(msg);
        System.out.println(msg);
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}


你可能感兴趣的:(Android)