文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

介绍下Netty中常用的编码器和解码器

2024-12-03 14:33

关注

前面文章介绍Netty相关知识点。接下来将介绍下在通信过程中用的编码器和解码器。这里会不会联想到谍战戏里面。发送情报者怕情报泄露,所以对情报行加密然后传给接收者。接收者对情报进行解密,得到情报。这里讲的编码器和解码器是和情报传递很相似?一起查看这篇文章,来揭秘!!!
1一 编解码器

1 1.1 什么叫编解码器

在网络传输的过程中,数据都是以字节流的方式进行传递。客户端在向服务端发送数据的时候,将业务中其他类型数据转化为字节,叫编码。服务端接收到数据为字节流,将字节流转化为原来的格式,叫解码。统称codec。

编解码器分为两部分-编码器和解码器,编码器负责出站,解码器负责入站。

2 1.2 解码器

1.2.1 概述

解码器负责入站操作,那么也一定要实现ChannelInboundHandler接口,所以解码器本质 上也是ChannelHandler。我们自定义编解码器只需要继承ByteToMessageDecoder(Netty提供抽象类,继承 ChannelInboundHandlerAdapter),实现decode()。Netty提供一些常用的解码器实现, 开箱即用。如下:

  1. 1 RedisDecoder 基于Redis协议的解码器 
  2. 2 XmlDecoder 基于XML格式的解码器 
  3. 3 JsonObjectDecoder 基于json数据格式的解码器 
  4. 4 HttpObjectDecoder 基于http协议的解码器 

Netty也提供了MessageToMessageDecoder,将⼀种格式转化为另⼀种格式的解码器,也提供了⼀些 实现,如下:

  1. 1 StringDecoder 将接收到ByteBuf转化为字符串 
  2. 2 ByteArrayDecoder 将接收到ByteBuf转化字节数组 
  3. 3 Base64Decoder 将由ByteBuf或US-ASCII字符串编码的Base64解码为ByteBuf。 

1.2.2 将字节流转化为Intger类型(案例)

1. 字节解码器

  1. package com.haopt.netty.codec; 
  2. import io.netty.buffer.ByteBuf; 
  3. import io.netty.channel.ChannelHandlerContext; 
  4. import io.netty.handler.codec.ByteToMessageDecoder; 
  5.  
  6. import java.util.List; 
  7. public class ByteToIntegerDecoder extends ByteToMessageDecoder { 
  8.      
  9.     @Override 
  10.     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { 
  11.         if(in.readableBytes() >= 4){ //int类型占⽤4个字节,所以需要判断是否存在有4个字节,再进⾏读取 
  12.             out.add(in.readInt()); //读取到int类型数据,放⼊到输出,完成数据类型的转化 
  13.         } 
  14.     } 
  15. 2. Handler

    1. package com.haopt.netty.codec; 
    2. import io.netty.channel.ChannelHandlerContext; 
    3. import io.netty.channel.ChannelInboundHandlerAdapter; 
    4. public class ServerHandler extends ChannelInboundHandlerAdapter { 
    5.     @Override 
    6.     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
    7.         Integer i = (Integer) msg; //这⾥可以直接拿到Integer类型的数据 
    8.         System.out.println("服务端接收到的消息为:" + i); 
    9.     } 

    3 在pipeline中添加解码器

    1. @Override 
    2. protected void initChannel(SocketChannel ch) throws Exception { 
    3.     ch.pipeline() 
    4.     .addLast(new ByteToIntegerDecoder()) 
    5.     .addLast(new ServerHandler()); 

    可以将代码复制到IDEA运行下,查看下运行效果。

    3 1.3 编码器

    1.3.1 概述

    将原来的格式转化为字节。我们要实现自定义解码器只要继承MessageToByteEncoder(实现了ChannelOutboundHandler接⼝),本质上也是ChannelHandler。Netty中一些实现的编码器,如下:

    1. 1 ObjectEncoder 将对象(需要实现Serializable接⼝)编码为字节流 
    2. 2 SocksMessageEncoder 将SocksMessage编码为字节流 
    3. 3 HAProxyMessageEncoder 将HAProxyMessage编码成字节流 

    Netty也提供了MessageToMessageEncoder,将⼀种格式转化为另⼀种格式的编码器,也提供了⼀些 实现:

    1. 1 RedisEncoder 将Redis协议的对象进⾏编码 
    2. 2 StringEncoder 将字符串进⾏编码操作 
    3. 3 Base64Encoder 将Base64字符串进⾏编码操作 

    1.3.2 将Integer类型编码为字节进⾏传递(案例)

    1. 自定义编码器

    1. package com.haopt.netty.codec.client; 
    2. import io.netty.buffer.ByteBuf; 
    3. import io.netty.channel.ChannelHandlerContext; 
    4. import io.netty.handler.codec.MessageToByteEncoder; 
    5. public class IntegerToByteEncoder extends MessageToByteEncoder<Integer> { 
    6.     @Override 
    7.     protected void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out) throws Exception { 
    8.        out.writeInt(msg); 
    9.     } 

    2. Handler

    1. package com.haopt.netty.codec.client; 
    2. import io.netty.buffer.ByteBuf; 
    3. import io.netty.buffer.Unpooled; 
    4. import io.netty.channel.ChannelHandlerContext; 
    5. import io.netty.channel.SimpleChannelInboundHandler; 
    6. import io.netty.util.CharsetUtil; 
    7. public class ClientHandler extends SimpleChannelInboundHandler { 
    8.     @Override 
    9.     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { 
    10.         System.out.println("接收到服务端的消息:" + 
    11.         msg.toString(CharsetUtil.UTF_8)); 
    12.     } 
    13.     @Override 
    14.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
    15.      ctx.writeAndFlush(123); 
    16.     } 
    17.     @Override 
    18.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
    19.      cause.printStackTrace(); 
    20.      ctx.close(); 
    21.     } 

    3. pipeline

    1. @Override 
    2. protected void initChannel(SocketChannel ch) throws Exception { 
    3.     ch.pipeline().addLast(new IntegerToByteEncoder()); 
    4.     ch.pipeline().addLast(new ClientHandler()); 

     2 二 开发Http服务器

    通过Netty中提供的http的解码器,进行http服务器开发。建议代码复制下来,执行下看看效果。

    4 2.1 Netty配置

    1. server

    1. package com.haopt.netty.codec.http; 
    2. import io.netty.bootstrap.ServerBootstrap; 
    3. import io.netty.channel.ChannelFuture; 
    4. import io.netty.channel.ChannelInitializer; 
    5. import io.netty.channel.EventLoopGroup; 
    6. import io.netty.channel.nio.NioEventLoopGroup; 
    7. import io.netty.channel.socket.SocketChannel; 
    8. import io.netty.channel.socket.nio.NioServerSocketChannel; 
    9. import io.netty.handler.codec.http.HttpObjectAggregator; 
    10. import io.netty.handler.codec.http.HttpRequestDecoder; 
    11. import io.netty.handler.codec.http.HttpResponseEncoder; 
    12. import io.netty.handler.stream.ChunkedWriteHandler; 
    13. public class NettyHttpServer { 
    14.     public static void main(String[] args) throws Exception { 
    15.         // 主线程,不处理任何业务逻辑,只是接收客户的连接请求 
    16.         EventLoopGroup boss = new NioEventLoopGroup(1); 
    17.         // ⼯作线程,线程数默认是:cpu*2 
    18.         EventLoopGroup worker = new NioEventLoopGroup(); 
    19.         try { 
    20.         // 服务器启动类 
    21.         ServerBootstrap serverBootstrap = new ServerBootstrap(); 
    22.         serverBootstrap.group(boss, worker); 
    23.         //配置server通道 
    24.         serverBootstrap.channel(NioServerSocketChannel.class); 
    25.         serverBootstrap.childHandler(new ChannelInitializer() { 
    26.             @Override 
    27.             protected void initChannel(SocketChannel ch) throws Exception { 
    28.                 ch.pipeline() 
    29.                 //http请求的解码器 
    30.                 //将http请求中的uri以及请求体聚合成⼀个完整的FullHttpRequest对象 
    31.                 .addLast(new HttpRequestDecoder())  
    32.                 .addLast(new HttpObjectAggregator(1024 * 128)) 
    33.                 .addLast(new HttpResponseEncoder()) //http响应的编码器 
    34.                 .addLast(new ChunkedWriteHandler()) //⽀持异步的⼤⽂件传输,防⽌内存溢出 
    35.                 .addLast(new ServerHandler()); 
    36.             } 
    37.           }); //worker线程的处理器 
    38.           ChannelFuture future = serverBootstrap.bind(8080).sync(); 
    39.           System.out.println("服务器启动完成。。。。。"); 
    40.           //等待服务端监听端⼝关闭 
    41.           future.channel().closeFuture().sync(); 
    42.         } finally { 
    43.           //优雅关闭 
    44.           boss.shutdownGracefully(); 
    45.           worker.shutdownGracefully(); 
    46.       } 
    47.      } 

    2. ServerHandler

    1. package com.haopt.netty.codec.http; 
    2. import io.netty.buffer.Unpooled; 
    3. import io.netty.channel.ChannelFutureListener; 
    4. import io.netty.channel.ChannelHandlerContext; 
    5. import io.netty.channel.ChannelInboundHandlerAdapter; 
    6. import io.netty.channel.SimpleChannelInboundHandler; 
    7. import io.netty.handler.codec.http.*; 
    8. import io.netty.util.CharsetUtil; 
    9. import java.util.Map; 
    10. public class ServerHandler extends SimpleChannelInboundHandler
    11.     @Override 
    12.     public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception { 
    13.         //解析FullHttpRequest,得到请求参数 
    14.         Map paramMap = new RequestParser(request).parse(); 
    15.         String name = paramMap.get("name"); 
    16.         //构造响应对象 
    17.         FullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); 
    18.         httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/html;charset=utf-8"); 
    19.         StringBuilder sb = new StringBuilder(); 
    20.         sb.append(""); 
    21.         httpResponse.content().writeBytes(Unpooled.copiedBuffer(sb,CharsetUtil.UTF_8)); 
    22.         //操作完成后,将channel关闭 
    23.         ctx.writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);  
    24.     } 

     3. RequestParser

    1. package com.haopt.netty.codec.http; 
    2. import io.netty.handler.codec.http.FullHttpRequest; 
    3. import io.netty.handler.codec.http.HttpMethod; 
    4. import io.netty.handler.codec.http.QueryStringDecoder; 
    5. import io.netty.handler.codec.http.multipart.Attribute; 
    6. import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; 
    7. import io.netty.handler.codec.http.multipart.InterfaceHttpData; 
    8. import java.io.IOException; 
    9. import java.util.HashMap; 
    10. import java.util.List; 
    11. import java.util.Map; 
    12.  
    13. public class RequestParser { 
    14.     private FullHttpRequest fullReq; 
    15.      
    16.     public RequestParser(FullHttpRequest req) { 
    17.      this.fullReq = req; 
    18.     } 
    19.      
    20.     public Map parse() throws Exception { 
    21.         HttpMethod method = fullReq.method(); 
    22.         Map parmMap = new HashMap<>(); 
    23.         if (HttpMethod.GET == method) { 
    24.           // 是GET请求 
    25.           QueryStringDecoder decoder = new QueryStringDecoder(fullReq.uri()); 
    26.           decoder.parameters().entrySet().forEach( entry -> { 
    27.           // entry.getValue()是⼀个List, 只取第⼀个元素 
    28.           parmMap.put(entry.getKey(), entry.getValue().get(0)); 
    29.           }); 
    30.         } else if (HttpMethod.POST == method) { 
    31.           // 是POST请求 
    32.           HttpPostRequestDecoder decoder = new 
    33.           HttpPostRequestDecoder(fullReq); 
    34.           decoder.offer(fullReq); 
    35.           List parmList = decoder.getBodyHttpDatas(); 
    36.           for (InterfaceHttpData parm : parmList) { 
    37.           Attribute data = (Attribute) parm; 
    38.           parmMap.put(data.getName(), data.getValue()); 
    39.           } 
    40.         } else { 
    41.           // 不⽀持其它⽅法 
    42.           throw new RuntimeException("不⽀持其它⽅法"); // 可以用自定义异常来替代 
    43.         } 
    44.         return parmMap; 
    45.     } 

    4. 对象

    1. package com.haopt.netty.codec.obj; 
    2. public class User implements java.io.Serializable { 
    3.     private static final long serialVersionUID = -89217070354741790L; 
    4.     private Long id; 
    5.     private String name
    6.     private Integer age; 
    7.     public Long getId() { 
    8.      return id; 
    9.     } 
    10.     public void setId(Long id) { 
    11.      this.id = id; 
    12.     } 
    13.     public String getName() { 
    14.      return name
    15.     } 
    16.     public void setName(String name) { 
    17.      this.name = name
    18.     } 
    19.     public Integer getAge() { 
    20.      return age; 
    21.     } 
    22.     public void setAge(Integer age) { 
    23.      this.age = age; 
    24.     } 
    25.     @Override 
    26.     public String toString() { 
    27.       return "User{" + 
    28.         "id=" + id + 
    29.         ", name='" + name + '\'' + 
    30.         ", age=" + age + 
    31.         '}'
    32.       } 

    5 2.2 服务端

    1. NettyObjectServer

    1. package com.haopt.netty.codec.obj; 
    2. import io.netty.bootstrap.ServerBootstrap; 
    3. import io.netty.channel.ChannelFuture; 
    4. import io.netty.channel.ChannelInitializer; 
    5. import io.netty.channel.EventLoopGroup; 
    6. import io.netty.channel.nio.NioEventLoopGroup; 
    7. import io.netty.channel.socket.SocketChannel; 
    8. import io.netty.channel.socket.nio.NioServerSocketChannel; 
    9. import io.netty.handler.codec.serialization.ClassResolvers; 
    10. import io.netty.handler.codec.serialization.ObjectDecoder; 
    11. public class NettyObjectServer { 
    12.     public static void main(String[] args) throws Exception { 
    13.         // 主线程,不处理任何业务逻辑,只是接收客户的连接请求 
    14.         EventLoopGroup boss = new NioEventLoopGroup(1); 
    15.         // ⼯作线程,线程数默认是:cpu*2 
    16.         EventLoopGroup worker = new NioEventLoopGroup(); 
    17.         try { 
    18.         // 服务器启动类 
    19.         ServerBootstrap serverBootstrap = new ServerBootstrap(); 
    20.         serverBootstrap.group(boss, worker); 
    21.         //配置server通道 
    22.         serverBootstrap.channel(NioServerSocketChannel.class); 
    23.         serverBootstrap.childHandler(new ChannelInitializer () { 
    24.             @Override 
    25.             protected void initChannel(SocketChannel ch) throws Exception { 
    26.                 ch.pipeline() 
    27.                 .addLast(new ObjectDecoder(ClassResolvers.weakCachingResolver( 
    28.                 this.getClass().getClassLoader() 
    29.                 ))) 
    30.                 .addLast(new ServerHandler()); 
    31.             } 
    32.         }); //worker线程的处理器 
    33.         ChannelFuture future = serverBootstrap.bind(6677).sync(); 
    34.         System.out.println("服务器启动完成。。。。。"); 
    35.         //等待服务端监听端⼝关闭 
    36.         future.channel().closeFuture().sync(); 
    37.         } finally { 
    38.         //优雅关闭 
    39.         boss.shutdownGracefully(); 
    40.         worker.shutdownGracefully(); 
    41.         } 
    42.     } 

    2. ServerHandler

    1. package com.haopt.netty.codec.obj; 
    2. import io.netty.buffer.Unpooled; 
    3. import io.netty.channel.ChannelHandlerContext; 
    4. import io.netty.channel.SimpleChannelInboundHandler; 
    5. import io.netty.util.CharsetUtil; 
    6. public class ServerHandler extends SimpleChannelInboundHandler<User> { 
    7.     @Override 
    8.     public void channelRead0(ChannelHandlerContext ctx, User user) throws Exception { 
    9.         //获取到user对象 
    10.         System.out.println(user); 
    11.         ctx.writeAndFlush(Unpooled.copiedBuffer("ok", CharsetUtil.UTF_8)); 
    12.     } 

    6 2.3 客户端

    1. NettyObjectClient

    1. package com.haopt.netty.codec.obj; 
    2. import io.netty.bootstrap.Bootstrap; 
    3. import io.netty.channel.ChannelFuture; 
    4. import io.netty.channel.ChannelInitializer; 
    5. import io.netty.channel.EventLoopGroup; 
    6. import io.netty.channel.nio.NioEventLoopGroup; 
    7. import io.netty.channel.socket.SocketChannel; 
    8. import io.netty.channel.socket.nio.NioSocketChannel; 
    9. import io.netty.handler.codec.serialization.ObjectEncoder; 
    10. public class NettyObjectClient { 
    11. public static void main(String[] args) throws Exception{ 
    12.     EventLoopGroup worker = new NioEventLoopGroup(); 
    13.         try { 
    14.             // 服务器启动类 
    15.             Bootstrap bootstrap = new Bootstrap(); 
    16.             bootstrap.group(worker); 
    17.             bootstrap.channel(NioSocketChannel.class); 
    18.             bootstrap.handler(new ChannelInitializer() { 
    19.                 @Override 
    20.                 protected void initChannel(SocketChannel ch) throws Exception { 
    21.                     ch.pipeline().addLast(new ObjectEncoder()); 
    22.                     ch.pipeline().addLast(new ClientHandler()); 
    23.                 } 
    24.             }); 
    25.             ChannelFuture future = bootstrap.connect("127.0.0.1", 6677).sync(); 
    26.             future.channel().closeFuture().sync(); 
    27.         } finally { 
    28.             worker.shutdownGracefully(); 
    29.         } 
    30.     } 

    2. ClientHandler

    1. package com.haopt.netty.codec.obj; 
    2. import io.netty.buffer.ByteBuf; 
    3. import io.netty.channel.ChannelHandlerContext; 
    4. import io.netty.channel.SimpleChannelInboundHandler; 
    5. import io.netty.util.CharsetUtil; 
    6. public class ClientHandler extends SimpleChannelInboundHandler { 
    7.     @Override 
    8.     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { 
    9.         System.out.println("接收到服务端的消息:" + 
    10.         msg.toString(CharsetUtil.UTF_8)); 
    11.     } 
    12.     @Override 
    13.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
    14.         User user = new User(); 
    15.         user.setId(1L); 
    16.         user.setName("张三"); 
    17.         user.setAge(20); 
    18.         ctx.writeAndFlush(user); 
    19.     } 
    20.     @Override 
    21.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 
    22.         cause.printStackTrace(); 
    23.         ctx.close(); 
    24.     } 

    7 2.4 JDK序列化的优化

    JDK序列化使⽤是⽐较⽅便,但是性能较差,序列化后的字节⽐较⼤,所以⼀般在项⽬中不 会使⽤⾃带的序列化,⽽是会采⽤第三⽅的序列化框架Hessian编解码。

    1. 导入依赖

    1.  
    2.   com.caucho 
    3.   hessian 
    4.   4.0.63 
    5.  

    2. User对象

    1. package com.haopt.netty.codec.hessian; 
    2. public class User implements java.io.Serializable
    3.     private static final long serialVersionUID = -8200798627910162221L; 
    4.     private Long id; 
    5.     private String name
    6.     private Integer age; 
    7.     public Long getId() { 
    8.      return id; 
    9.     } 
    10.     public void setId(Long id) { 
    11.      this.id = id; 
    12.     } 
    13.     public String getName() { 
    14.      return name
    15.     } 
    16.     public void setName(String name) { 
    17.      this.name = name
    18.     } 
    19.     public Integer getAge() { 
    20.      return age; 
    21.     } 
    22.     public void setAge(Integer age) { 
    23.      this.age = age; 
    24.     } 
    25.     @Override 
    26.     public String toString() { 
    27.       return "User{" + 
    28.       "id=" + id + 
    29.       ", name='" + name + '\'' + 
    30.       ", age=" + age + 
    31.       '}'
    32.     } 

    3. Hessian序列化⼯具类

    1. package com.haopt.netty.codec.hessian.codec; 
    2. import com.caucho.hessian.io.HessianInput; 
    3. import com.caucho.hessian.io.HessianOutput; 
    4. import java.io.ByteArrayInputStream; 
    5. import java.io.ByteArrayOutputStream; 
    6. import java.io.IOException; 
    7.  
    8. public class HessianSerializer { 
    9.     public  byte[] serialize(T obj) { 
    10.         ByteArrayOutputStream os = new ByteArrayOutputStream(); 
    11.         HessianOutput ho = new HessianOutput(os); 
    12.         try { 
    13.           ho.writeObject(obj); 
    14.           ho.flush(); 
    15.           return os.toByteArray(); 
    16.         } catch (IOException e) { 
    17.          throw new RuntimeException(e); 
    18.         } finally { 
    19.           try { 
    20.            ho.close(); 
    21.           } catch (IOException e) { 
    22.            throw new RuntimeException(e); 
    23.           } 
    24.           try { 
    25.            os.close(); 
    26.           } catch (IOException e) { 
    27.           throw new RuntimeException(e); 
    28.           } 
    29.         } 
    30.      } 
    31.       
    32.      public  Object deserialize(byte[] bytes, Class clazz) { 
    33.         ByteArrayInputStream is = new ByteArrayInputStream(bytes); 
    34.         HessianInput hi = new HessianInput(is); 
    35.         try { 
    36.           return (T) hi.readObject(clazz); 
    37.         } catch (IOException e) { 
    38.           throw new RuntimeException(e); 
    39.         } finally { 
    40.             try { 
    41.                hi.close(); 
    42.             } catch (Exception e) { 
    43.             throw new RuntimeException(e); 
    44.         } 
    45.         try { 
    46.           is.close(); 
    47.         } catch (IOException e) { 
    48.           throw new RuntimeException(e); 
    49.         } 
    50.       } 
    51.     } 

    4. 编码器

    1. package com.haopt.netty.codec.hessian.codec; 
    2. import cn.itcast.netty.coder.hessian.User
    3. import io.netty.buffer.ByteBuf; 
    4. import io.netty.channel.ChannelHandlerContext; 
    5. import io.netty.handler.codec.MessageToByteEncoder; 
    6. public class HessianEncoder extends MessageToByteEncoder<User> { 
    7.     private HessianSerializer hessianSerializer = new HessianSerializer(); 
    8.     protected void encode(ChannelHandlerContext ctx, User msg, ByteBuf out) throws Exception { 
    9.           byte[] bytes = hessianSerializer.serialize(msg); 
    10.           out.writeBytes(bytes); 
    11.     } 

    5. 解码器

    1. public class HessianDecoder extends ByteToMessageDecoder { 
    2.     private HessianSerializer hessianSerializer = new HessianSerializer(); 
    3.  
    4.     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List 
    5.             out) throws Exception { 
    6.         //复制⼀份ByteBuf数据,轻复制,⾮完全拷⻉ 
    7.         //避免出现异常:did not read anything but decoded a message 
    8.         //Netty检测没有读取任何字节就会抛出该异常 
    9.         ByteBuf in2 = in.retainedDuplicate(); 
    10.         byte[] dst; 
    11.         if (in2.hasArray()) {//堆缓冲区模式 
    12.             dst = in2.array(); 
    13.         } else { 
    14.             dst = new byte[in2.readableBytes()]; 
    15.             in2.getBytes(in2.readerIndex(), dst); 
    16.         } 
    17.         //跳过所有的字节,表示已经读取过了 
    18.         in.skipBytes(in.readableBytes()); 
    19.         //反序列化 
    20.         Object obj = hessianSerializer.deserialize(dst, User.class); 
    21.         out.add(obj); 
    22.     } 
    23. 服务端

      1. public class NettyHessianServer { 
      2.     public static void main(String[] args) throws Exception { 
      3.         // System.setProperty("io.netty.noUnsafe""true"); 
      4.         // 主线程,不处理任何业务逻辑,只是接收客户的连接请求 
      5.         EventLoopGroup boss = new NioEventLoopGroup(1); 
      6.         // ⼯作线程,线程数默认是:cpu*2 
      7.         EventLoopGroup worker = new NioEventLoopGroup(); 
      8.         try { 
      9.             // 服务器启动类 
      10.             ServerBootstrap serverBootstrap = new ServerBootstrap(); 
      11.             serverBootstrap.group(boss, worker); 
      12.             //配置server通道 
      13.             serverBootstrap.channel(NioServerSocketChannel.class); 
      14.             serverBootstrap.childHandler(new ChannelInitializer 
      15.                     () { 
      16.                 @Override 
      17.                 protected void initChannel(SocketChannel ch) throws Exception { 
      18.                     ch.pipeline() 
      19.                             .addLast(new HessianDecoder()) 
      20.                             .addLast(new ServerHandler()); 
      21.                 } 
      22.             }); //worker线程的处理器 
      23.             // serverBootstrap.childOption(ChannelOption.ALLOCATOR, 
      24.             UnpooledByteBufAllocator.DEFAULT); 
      25.             ChannelFuture future = serverBootstrap.bind(6677).sync(); 
      26.             System.out.println("服务器启动完成。。。。。"); 
      27.             //等待服务端监听端⼝关闭 
      28.             future.channel().closeFuture().sync(); 
      29.         } finally { 
      30.             //优雅关闭 
      31.             boss.shutdownGracefully(); 
      32.             worker.shutdownGracefully(); 
      33.         } 
      34.     } 

      1. public class ServerHandler extends SimpleChannelInboundHandler<User> { 
      2.     @Override 
      3.     public void channelRead0(ChannelHandlerContext ctx, User user) throws 
      4.             Exception { 
      5.         //获取到user对象 
      6.         System.out.println(user); 
      7.         ctx.writeAndFlush(Unpooled.copiedBuffer("ok", CharsetUtil.UTF_8)); 
      8.     } 

      7. 客户端(配置类)

      1. public class NettyHessianClient { 
      2.     public static void main(String[] args) throws Exception { 
      3.         EventLoopGroup worker = new NioEventLoopGroup(); 
      4.         try { 
      5.             // 服务器启动类 
      6.             Bootstrap bootstrap = new Bootstrap(); 
      7.             bootstrap.group(worker); 
      8.             bootstrap.channel(NioSocketChannel.class); 
      9.             bootstrap.handler(new ChannelInitializer() { 
      10.                 @Override 
      11.                 protected void initChannel(SocketChannel ch) throws Exception { 
      12.                     ch.pipeline().addLast(new HessianEncoder()); 
      13.                     ch.pipeline().addLast(new ClientHandler()); 
      14.                 } 
      15.             }); 
      16.             ChannelFuture future = bootstrap.connect("127.0.0.1", 6677).sync(); 
      17.             future.channel().closeFuture().sync(); 
      18.         } finally { 
      19.             worker.shutdownGracefully(); 
      20.         } 
      21.     } 

      1. public class ClientHandler extends SimpleChannelInboundHandler { 
      2.     @Override 
      3.     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws 
      4.             Exception { 
      5.         System.out.println("接收到服务端的消息:" + 
      6.                 msg.toString(CharsetUtil.UTF_8)); 
      7.     } 
      8.  
      9.     @Override 
      10.     public void channelActive(ChannelHandlerContext ctx) throws Exception { 
      11.         User user = new User(); 
      12.         user.setId(1L); 
      13.         user.setName("张三"); 
      14.         user.setAge(20); 
      15.         ctx.writeAndFlush(user); 
      16.     } 
      17.  
      18.     @Override 
      19.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 
      20.             throws Exception { 
      21.         cause.printStackTrace(); 
      22.         ctx.close(); 
      23.     } 

      这篇文章,介绍了什么是编码器、解码器,也讲述了如何实战中运用编码器和解码器。希望能对有所帮助。在开头提到的我们本文的编码器解码器和情报信息交互是否相似?在我看来,是相似的。发报人将自己看的懂得信息,按照某种规则进行加密。收报人接收到信息是加密后的数据,需要进行按照规则进行解密才能看懂。我们客户端在进行发送数据,需要将程序中的数据变为二进制流发送。服务端接收到数据,需要将二进制流转化为程序可以操作数据类型。

       

      免责声明:

      ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

      ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

      软考中级精品资料免费领

      • 历年真题答案解析
      • 备考技巧名师总结
      • 高频考点精准押题
      • 资料下载
      • 历年真题
      • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

        难度     813人已做
        查看
      • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

        难度     354人已做
        查看
      • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

        难度     318人已做
        查看
      • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

        难度     435人已做
        查看
      • 2024年上半年系统架构设计师考试综合知识真题

        难度     224人已做
        查看

      相关文章

      发现更多好内容
      咦!没有更多了?去看看其它编程学习网 内容吧