Encode、Decode

在这里插入图片描述

import java.io.Serializable;

public class Dog implements Serializable {

  // 名字
  private String name;

  // 品种
  private String type;

  // 颜色
  private String color;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  public String getColor() {
    return color;
  }

  public void setColor(String color) {
    this.color = color;
  }
}

import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

public class MsgEncoder extends MessageToByteEncoder<Dog> {

  @Override
  protected void encode(ChannelHandlerContext ctx, Dog msg, ByteBuf out) throws Exception {
    //将对象转换为byte
    byte[] body = convertToBytes(msg);
    System.out.println("Dog convert to bytes");
    if (body == null || body.length < 1) {
      return;
    }

    //读取消息的长度
    int dataLength = body.length;
    //先将消息长度写入,也就是消息头
    out.writeInt(dataLength);
    //消息体中包含我们要发送的数据
    out.writeBytes(body);
  }

  private byte[] convertToBytes(Dog dog) {
    if (dog == null) {
      return null;
    }

    try {
      // 对象装好为 json 格式字符串
      String contentString = JSON.toJSONString(dog);
      // 字符串转换为 byte 数组
      return contentString.getBytes("GBK");
    } catch (Exception e) {
      System.out.println("Dog convert to bytes error. ");
      e.printStackTrace();
    }

    return null;
  }
}

import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;

public class MsgDecoder extends ByteToMessageDecoder {

  private static final int HEAD_LENGTH = 4;

  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

    //这个HEAD_LENGTH是我们用于表示头长度的字节数。 由于Encoder中我们传的是一个int类型的值,所以这里HEAD_LENGTH的值为4.
    if (in.readableBytes() < HEAD_LENGTH) {
      return;
    }

    //我们标记一下当前的readIndex的位置
    in.markReaderIndex();
    // 读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4
    int dataLength = in.readInt();

    // 我们读到的消息体长度为0,这是不应该出现的情况,这里出现这情况,关闭连接。
    if (dataLength < 0) {
      ctx.close();
    }

    //读到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
    if (in.readableBytes() < dataLength) {
      in.resetReaderIndex();
      return;
    }

    //传输正常
    byte[] body = new byte[dataLength];
    in.readBytes(body);
    //将byte数据转化为我们需要的对象
    Object o = convertToObject(body);
    System.out.println("bytes convert to Dog");
    out.add(o);
  }

  private Object convertToObject(byte[] body) {
    if (body == null || body.length < 1) {
      return null;
    }

    String contentString = null;
    try {
      contentString = new String(body, "GBK");
    } catch (Exception e) {
    }

    if (contentString == null || contentString.length() < 1) {
      return null;
    }

    try {
      Dog dog = JSON.parseObject(contentString, Dog.class);
      return dog;
    } catch (Exception e) {
      System.out.println("bytes convert to Dog error. ");
      e.printStackTrace();
    }

    return contentString;
  }
}

在这里插入图片描述

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

@Component
public class ObjectServer {

  /**
   * 创建bootstrap
   */
  private static final ServerBootstrap serverBootstrap = new ServerBootstrap();

  /**
   * Worker
   */
  private static final EventLoopGroup work = new NioEventLoopGroup();

  /**
   * 端口号
   */
  private int port = getPort();

  /**
   * 关闭服务器方法
   */
  public void close() {
    System.out.println("关闭服务器....");
    //优雅退出
    work.shutdownGracefully();
  }

  /**
   * 开启及服务线程
   */
  public void start() {
    serverBootstrap.group(work)
        .channel(NioServerSocketChannel.class)
        .option(ChannelOption.SO_BACKLOG, 100)
        .handler(new LoggingHandler(LogLevel.INFO));
    try {
      //设置事件处理
      serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
          ChannelPipeline pipeline = ch.pipeline();
          pipeline.addLast( new MsgEncoder());
          pipeline.addLast(new MsgDecoder());
          pipeline.addLast(new ServerObjectHandler());

        }
      });
      System.out.println("netty服务器在[" + port + "]端口启动监听");
      ChannelFuture f = serverBootstrap.bind(port);
      f.channel().closeFuture();
    } catch (Exception e) {
      System.out.println("[出现异常] 释放资源");
    } finally {
      close();
    }
  }

  private static int getPort() {
    Double port = (Math.random() + 1) * 10000;
    return port.intValue();
  }

  public static void main(String[] args) {
    ObjectServer nsl = new ObjectServer();
    nsl.start();

在这里插入图片描述

public class ServerObjectHandler extends ChannelInboundHandlerAdapter {

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    System.out.println("some error. ");
    cause.printStackTrace();
    ctx.close();
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) {
    // 具体处理客户端的数据信息
    Dog dog = (Dog) msg;
    System.out.println(
        "receive message. name=" + dog.getName() + ",type=" + dog.getType() + ",color=" + dog
            .getColor()
    );

    // 返回给客户端一个新的对象
    Dog returnDog = new Dog();
    returnDog.setName("MaoMao");
    returnDog.setType("JinMao");
    returnDog.setColor("yellow");
    ctx.writeAndFlush(returnDog);
  }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值