悉野小楼

导航

netty echo例子

netty使用方法:
1. 选择事件处理线程池EventLoopGroup, 要与下面的管道选择对应名称, 服务端要两个(一个是接收客户端连接,另一个是处理客户端请求), 客户端只需要一个(处理客户端请求)
2. 创建Bootstrap对象, 配置事件处理线程池(上面new的Group)
3. 设置管道(有NioSocketChannel, EpollSocketChannel(linux下可用), LocalServerChannel(可能本地通信, 127.0.0.1之间))
4. 设置绑定的端口和主机名 如果是服务端就localAddress(8080), 如果是客户端就remoteAddress("127.0.0.1", 8080)
5. 绑定客户端处理类服务端使用childHandler, 客户端使用handler
6. 调用connect()方法, 阻塞直到连接成功
7. 阻塞直到channel关闭
8. 关闭线程池

例子代码下载

EchoServer.java

package org.example.echo;

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

public class EchoServer {

    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class).localAddress(8080);
            //serverBootstrap.channel(EpollServerSocketChannel.class);
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new EchoServerHandler());
                }
            });
            ChannelFuture channelFuture = serverBootstrap.bind().sync(); // 绑定端口,并同步等待成功
            channelFuture.channel().closeFuture().sync(); // 同步等待关闭channel
        } catch (Exception ex) {
            try {
                workerGroup.shutdownGracefully().sync();
            } catch(Exception e) { }
            try {
                bossGroup.shutdownGracefully();
            } catch (Exception e) {}
        }
    }
}

EchoServerHandler.java

package org.example.echo;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.util.CharsetUtil;

import java.net.SocketAddress;

//@ChannelHandler.Sharable 标示一个Channel- Handler可以被多个Channel安全地共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        SocketAddress address = ctx.channel().localAddress();
        System.out.println("收到连接 address:" + address.toString());
        // ctx.writeAndFlush("this is server's msg"); //直接写字符串收不到
        // ctx.writeAndFlush("this is server's msg".getBytes()); //直接写字节数组收不到
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello, this is server:" + Thread.currentThread().getId(),
                CharsetUtil.UTF_8));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress address = ctx.channel().localAddress();
        System.out.println("连接断开 address:" + address.toString());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //ctx.fireChannelRead(msg);
        ByteBuf in = (ByteBuf) msg;
        // 打印消息
        System.out.println("Server received: " + in.toString(io.netty.util.CharsetUtil.UTF_8));
        // 返回给客户端
        ctx.writeAndFlush(in);
    }

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

EchoClient.java

package org.example.echo;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class EchoClient {

    public static void main(String[] args) {
        NioEventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)  //指定客户端处理事件group
                .channel(NioSocketChannel.class); //NioSocketChannel
        bootstrap.remoteAddress("127.0.0.1", 8080); //指定服务器地址
        bootstrap.handler(new ChannelInitializer<NioSocketChannel>(){
            @Override
            protected void initChannel(NioSocketChannel ch) throws Exception {
                ch.pipeline().addLast(new EchoClientHandler());
            }
        });
        try {
            ChannelFuture future = bootstrap.connect().sync(); //阻塞并连结到远程结点
            future.channel().closeFuture().sync(); //阻塞直到channel关闭
        } catch (Exception ex){

        } finally {
            group.shutdownGracefully(); //关闭线程池
        }
    }
}

EchoClientHandler.java

package org.example.echo;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;

import java.net.SocketAddress;

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    public EchoClientHandler() {
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress address = ctx.channel().localAddress();
        System.out.println("建立连接 address:" + address.toString());
        //直按发字符串或字节数组, 服务端收不到, 要使用Unpooled.copiedBuffer包裹
        ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!",
                CharsetUtil.UTF_8));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress address = ctx.channel().localAddress();
        System.out.println("连接断开 address:" + address.toString());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        //ctx.fireChannelRead(msg);
        ByteBuf in = (ByteBuf) msg;
        // 打印消息
        System.out.println("收到回应: " + in.toString(io.netty.util.CharsetUtil.UTF_8));
        // 返回给客户端
        Thread.sleep(1000);
        //直按发字符串或字节数组, 服务端收不到, 要使用Unpooled.copiedBuffer包裹
        ctx.writeAndFlush(Unpooled.copiedBuffer("current Time:" + System.currentTimeMillis(), CharsetUtil.UTF_8));
    }

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

 

posted on 2024-12-18 16:50  悉野  阅读(3)  评论(0编辑  收藏  举报