Netty 4.x 实战详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lms1719/article/details/70314645

Netty 4.x 实战详解

目前Netty的最新稳定版本是 Netty 4.1.9, 本文根据该版本进行开发介绍。

开发前准备工作:

  • 到Netty官网(http://netty.io/downloads.html),下载开始所需的Netty包:netty-all-4.1.9.Final.jar;

  • 安装Java开发环境,这里使用的是Jdk8;

  • 这里使用的编辑器是Intellij IDEA,也可以根据自己的喜好,选择其他的,比如Eclipse等。


接下来,我们用Netty实现一个demo。主要功能如下:

  • 1、服务端启动,等待接受客户端的连接和处理请求;

  • 2、客户端启动和服务端建立连接,服务器返回“连接成功!”;

  • 3、客户端和服务器进行数据传输操作。


代码实现

这里写图片描述

一、 服务器

1、服务器启动逻辑(DemoServer.java)

package server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * 服务器启动逻辑
 */
public class DemoServer {

    public static void main(String[] args) throws Exception {
        int port = 8000;
        if (args != null && args.length > 0) {
            try {
                port = Integer.valueOf(args[0]);
            } catch (NumberFormatException e) {
                //采用默认值
            }
        }
        new DemoServer().bind(port);
    }

    public void bind(int port) throws Exception {
        //配置服务端的NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ServerChannelInitializer());

            //绑定端口,同步等待成功
            ChannelFuture f = b.bind(port).sync();

            //等待服务器监听端口关闭
            f.channel().closeFuture().sync();
        } finally {
            //优雅退出,释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2、服务器Channel通道初始化设置(ServerChannelInitializer .java)

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 服务器Channel通道初始化设置
 */
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        //字符串解码和编码
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());
        //服务器的逻辑
        pipeline.addLast("handler", new DemoServerHandler());
    }
}

3、服务器业务逻辑(DemoServerHandler.java)

package server;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.net.Inet4Address;

/**
 * 服务器业务逻辑
 */
public class DemoServerHandler extends SimpleChannelInboundHandler {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Client say : " + msg.toString());
        //返回客户端消息 - 我已经接收到了你的消息
        ctx.writeAndFlush("Received your message : " + msg.toString());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("RemoteAddress : " + ctx.channel().remoteAddress() + " active !");
        ctx.writeAndFlush("连接成功!");
        super.channelActive(ctx);
    }
}

二、 客户端

1、客户端启动逻辑(DemoClient.java)

package client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * 客户端启动逻辑
 */
public class DemoClient {

    public static String host = "127.0.0.1"; //服务器IP地址
    public static int port = 8000; //服务器端口

    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ClientChannelInitializer());

            //连接客户端
            Channel channel = b.connect(host, port).sync().channel();

            //控制台输入
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

            for (;;) {
                String line = in.readLine();
                if (line == null) {
                    continue;
                }
                //向服务端发送数据
                channel.writeAndFlush(line);
            }
        } finally {
            //优雅退出,释放线程池资源
            group.shutdownGracefully();
        }
    }
}

2、客户端Channel通道初始化设置(ClientChannelInitializer .java)

package client;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 客户端Channel通道初始化设置
 */
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        //字符串解码和编码
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());
        //客户端的逻辑
        pipeline.addLast("handler", new DemoClientHandler());
    }
}

3、客户端业务逻辑(DemoClientHandler.java)

package client;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 客户端业务逻辑
 */
public class DemoClientHandler extends SimpleChannelInboundHandler {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("Server say : " + msg.toString());
    }
}

运行结果

  • 先启动服务器,再启动客户端。

这里写图片描述

这里写图片描述

  • 在客户端的控制台输入“服务端,你好!”,然后按“Enter”键,将数据发送到服务端。

这里写图片描述

这里写图片描述

参考书籍:Netty in action 和 Netty 权威指南

猜你喜欢

转载自blog.csdn.net/lms1719/article/details/70314645
今日推荐