zoukankan      html  css  js  c++  java
  • netty Demo

    今天写了一个helloworld版本的netty程序,跟大家分享一下:

    首先需要的包是:netty-all-4.1.25.Final.jar

    客户端:

    StrClient.java

    package client;

    import java.net.InetSocketAddress;

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

    /**
    *1. 搞一个Bootstrop 对象
    *
    *2. 封装Bootstrop 对象
    *
    *3. 写Handler类 也就是所有的业务逻辑
    *
    * @author zx
    *
    */
    public class StrClient {
    //分配一个ip和端口号
    private String host;
    private int port;
    private NioEventLoopGroup nioEventLoopGroup;
    public StrClient(String host, int port) {
    this.host = host;
    this.port = port;
    }

    //启动项目 ip地址是 本地 端口号是888
    public static void main(String[] args) throws InterruptedException {
    new StrClient("localhost", 888).start();
    }

    public void start() throws InterruptedException {
    try {
    //客户端的引导类,启动网络客户端 Bootstrap有很多客户端的属性
    Bootstrap bootstrap = new Bootstrap();
    //可以理解成是一个线程池,用这个线程池来处理连接和接收数据
    nioEventLoopGroup = new NioEventLoopGroup();
    bootstrap.group(nioEventLoopGroup) //多线程处理,注册一下这个组
    .channel(NioSocketChannel.class) //制定通道类型是NioSocketChannel
    .remoteAddress(new InetSocketAddress(host, port)) //注册远程服务器的地址
    .handler(new ChannelInitializer<SocketChannel>() {
    //////////////↑模板代码/////////////
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    //业务逻辑
    ch.pipeline().addLast(new StrClientHandler());
    }
    //////////////↓模板代码/////////////
    });
    //开始连接服务器
    ChannelFuture channelFuture = bootstrap.connect().sync(); //等到连接成功,否则一直阻塞线程
    channelFuture.channel().closeFuture().sync(); //接收数据之后阻塞
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    nioEventLoopGroup.shutdownGracefully().sync();
    }
    }
    }

    StrClientHandler.java

    package client;

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

    public class StrClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    //客户端连接服务器后会调用 这里面可以发送请求
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println("client -> 开始连接服务器发送数据...");
    byte[] bytes = "get current time".getBytes();
    ByteBuf buffer = Unpooled.buffer(bytes.length); //构造一个数组存数据
    buffer.writeBytes(bytes); //给buffer写数据 在数组里面写入的数据
    ctx.writeAndFlush(buffer); //将这个信息交给上下文 进入pipline 如果有第二个Handler也会把这个数据给这第二个Handler
    }

    //从服务器端接到数据之后
    @Override
    protected void channelRead0(ChannelHandlerContext ch, ByteBuf msg) throws Exception {
    System.out.println("client -> 读取服务器返回的对象...");
    //反序列化
    byte [] bytes = new byte [msg.readableBytes()]; //将这个2进制的数据写入数组里
    msg.readBytes(bytes); //实际上是写入数组中
    String messageBody = new String (bytes,"UTF-8");
    System.out.println("client -> 接到数据,内容是: " + messageBody);
    }

    //发生异常的时候会调用
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    //打印出错的原因
    cause.printStackTrace();
    //发生异常的时候就会关闭这个上下文,中断数据的传输
    ctx.close();
    }

    }

    服务端:

    StrServer.java

    package server;

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

    public class StrServer {
    private int port;
    private NioEventLoopGroup nioEventLoopGroup;

    public StrServer(int port) {
    this.port = port;
    }

    public static void main(String[] args) throws InterruptedException {
    new StrServer(888).start();
    }

    private void start() throws InterruptedException {
    try {
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    nioEventLoopGroup = new NioEventLoopGroup();
    serverBootstrap.group(nioEventLoopGroup)
    .channel(NioServerSocketChannel.class)
    .localAddress("localhost", port)
    .childHandler(new ChannelInitializer<Channel>() {
    //业务逻辑
    @Override
    protected void initChannel(Channel ch) throws Exception {
    ch.pipeline().addLast(new StrServerHandler());
    }
    });
    ChannelFuture channelFuture = serverBootstrap.bind().sync();
    System.out.println("Server -> 服务启动成功 监听端口, " + port);
    channelFuture.channel().closeFuture().sync();
    }catch (Exception e) {
    e.printStackTrace();
    } finally {
    nioEventLoopGroup.shutdownGracefully().sync();
    }
    }
    }

    StrServerHandler.java

    package server;

    import java.util.Date;

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;

    public class StrServerHandler extends ChannelInboundHandlerAdapter {

    /**
    *
    *@param ctx 上下文
    *@param msg 传来的具体的数据
    *
    */
    //读取客户端发来的数据 这个方法会被调起,在服务器读取数据的时候
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    System.out.println("Server -> 接到数据,开始处理...");
    ByteBuf buf = (ByteBuf)msg; //将传过来的ByteBuf强制转换
    byte [] req = new byte[buf.readableBytes()]; //2进制数组
    buf.readBytes(req); //将req的内容写到buf中
    //反序列化
    String requestbody = new String (req, "UTF-8");
    System.out.println("Server -> 客户端请求数据是: " + requestbody);
    System.out.println("Server -> 开始写回数据");
    String currentTime = new Date().toString();
    //封装了数据的输出
    ByteBuf copiedBuffer = Unpooled.copiedBuffer(currentTime.getBytes());
    ctx.write(copiedBuffer);

    }

    //数据读取完成会调起
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    ctx.flush();
    }


    //发生异常会被调用
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    ctx.close();
    cause.printStackTrace();
    }
    }

    运行服务端和客户端的main即可启动服务,

    1. 服务端准备接受客户端的请求信息;

    2. 客户端请求: get currentTime 

    3. 服务端获取到请求信息:get currentTime

    4. 服务端准备返回数据: String responseBody = new Date() . toString();

    5. 服务端返回数据

    6. 客户端获取服务端返回的数据

  • 相关阅读:
    POST数据中有特殊符号导致数据丢失的解决方法
    Javascript中bind()方法的使用与实现
    Vue插件写、用详解(附demo)
    js自定义事件、DOM/伪DOM自定义事件
    对象可枚举和不可枚举属性
    js 数组 map方法
    Java源码学习(JDK 11)——java.util.concurrent.CopyOnWriteArrayList
    Java源码学习(JDK 11)——java.util.Collections
    Java源码学习(JDK 11)——java.util.Arrays
    Java源码学习(JDK 11)——java.lang.Collection
  • 原文地址:https://www.cnblogs.com/zx947240023/p/9178843.html
Copyright © 2011-2022 走看看