二、Netty學習:Socket開發

一、Netty的常見應用場景

  • 構建HTTP服務器
  • Socket開發
  • 基於HTTP長連接開發

二、Socket開發示例

1. 服務端開發

1.1 主函數

public class Server {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();

            ChannelFuture future = bootstrap.group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ServerInitializer())
                    .bind(8899)
                    .sync();

            future.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }
}

1.2 Initializer類

public class ServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
        pipeline.addLast(new LengthFieldPrepender(4));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(new ChannelHandle());
    }
}

1.3 Handle類

public class ChannelHandle extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("請求地址:" + ctx.channel().remoteAddress() + ", 請求消息:" + msg);
        ctx.writeAndFlush("From server: " + msg + ", " + UUID.randomUUID());
    }

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

2. 客戶端開發

2.1 主函數

public class Client {

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.handler(new ClientInitializer());

            ChannelFuture future = bootstrap.connect("localhost", 8899);
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

2.1 Initializer類

public class ClientInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
        pipeline.addLast(new LengthFieldPrepender(4));
        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
        pipeline.addLast(new ChannelHandle());
    }
}

2.3 Handle類

public class ChannelHandle extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("remote address: " + ctx.channel().remoteAddress());
        System.out.println("from server: " + msg);
        ctx.writeAndFlush("from client: " + LocalDateTime.now());
    }

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

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

3. 執行結果

  • 服務端
請求地址:/127.0.0.1:50796, 請求消息:from client: 2019-12-01T23:06:06.953
  • 客戶端

在服務端和客戶端都啓動後會發現服務端不斷的接收到客戶端的請求,客戶端不斷地響應着服務端的返回

4. 執行流程

  1. 服務端啓動
  2. 客戶端啓動,執行ChannelHandle中的channelActive方法,向服務端發送消息
  3. 服務端的ChannelHandle中的channelRead0進行響應處理,並向客戶端響應消息
  4. 客戶端的ChannelHandle中的channelRead0響應服務端的響應,並向服務端發送消息
  5. 重複3,4步驟
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章