在线快速建站,作品集设计,怎么添加网站程序,抖音小程序权限怎么关闭目录
什么是编解码器#xff1f;
解码器
将字节解码为消息
将一种消息类型解码为另一种
TooLongFrameException
编码器
将消息编码为字节
将消息编码为消息
编解码器类
通过http协议实现SSL/TLS和Web服务 什么是编解码器#xff1f; 每个网络应用程序都必须定义如何…目录
什么是编解码器
解码器
将字节解码为消息
将一种消息类型解码为另一种
TooLongFrameException
编码器
将消息编码为字节
将消息编码为消息
编解码器类
通过http协议实现SSL/TLS和Web服务 什么是编解码器 每个网络应用程序都必须定义如何解析在两个节点之间来回传输的原始字节以及如何将其和目标应用程序的数据格式做相互转换。这种转换逻辑由编解码器处理编解码器由编码器和解码器组成它们每种都可以将字节流从一种格式转换为另一种格式。 如果将消息看作是对于特定的应用程序具有具体含义的结构化的字节序列—它的数据。那么编码器是将消息转换为适合于传输的格式最有可能的就是字节流。而对应的解码器则是将网络字节流转换回应用程序的消息格式。因此编码器操作出站数据而解码器处理入站数据。
解码器 将字节解码为消息——ByteToMessageDecoder。 将一种消息类型解码为另一种——MessageToMessageDecoder。 因为解码器是负责将入站数据从一种格式转换到另一种格式的所以 Netty 的解码器实现了 ChannelInboundHandler。 比如一个实际的业务场景两端通信通过 JSON 交换信息而且 JSON 文本需要加密接收端就可以 网络加密报文 - 经过 ByteToMessageDecoder - String 类型的JSON明文。 String 类型的 JSON 文本- 经过 MessageToMessageDecoder - Java 里的对象。 将字节解码为消息 抽象类 ByteToMessageDecoder 将字节解码为消息或者另一个字节序列是一项如此常见的任务Netty 为它提供了一个抽象的基类ByteToMessageDecoder。由于你不可能知道远程节点是否会一次性地发送一个完整的消息所以这个类会对入站数据进行缓冲直到它准备好处理。 它最重要方法decode(ChannelHandlerContext ctx,ByteBuf in,Listout)。是必须实现的唯一抽象方法。decode()方法被调用时将会传入一个包含了传入数据的 ByteBuf以及一个用来添加解码消息的 List。对这个方法的调用将会重复进行直到确定没 有新的元素被添加到该 List或者该 ByteBuf 中没有更多可读取的字节时为止。然后如果 该 List 不为空那么它的内容将会被传递给 ChannelPipeline 中的下一个 ChannelInboundHandler。 将一种消息类型解码为另一种 在两个消息格式之间进行转换例如从 String-Integer方decode(ChannelHandlerContext ctx,I msg,Listout) 对于每个需要被解码为另一种格式的入站消息来说该方法都将会被调用。解码消息随 后会被传递给 ChannelPipeline 中的下一个 ChannelInboundHandler。MessageToMessageDecoderT 代表源数据的类型。 TooLongFrameException 由于 Netty 是一个异步框架所以需要在字节可以解码之前在内存中缓冲它们。因此不能让解码器缓冲大量的数据以至于耗尽可用的内存。为了解除这个常见的顾虑Netty 提供了 TooLongFrameException 类其将由解码器在帧超出指定的大小限制时抛出。 为了避免这种情况你可以设置一个最大字节数的阈值如果超出该阈值则会导致抛出一个TooLongFrameException随后会被ChannelHandler.exceptionCaught()方法捕获。然后如何处理该异常则完全取决于该解码器的用户。某些协议如HTTP可能允许你返回一个特殊的响应。而在其他的情况下唯一的选择可能就是关闭对应的连接。 编码器 解码器的功能正好相反。Netty 提供了一组类用于帮助你编写具有以下功能的编码器将消息编码为字节。MessageToByteEncoder 将消息编码为消息MessageToMessageEncoderT代表源数据的类型。 比如两端通信通过 JSON 交换信息而且 JSON 文本需要加密发送端就可以
Java 里的对象- 经过 MessageToMessageEncoder - String类型的JSON文本。
String 类型的 JSON 明文 - 经过 MessageToByteEncoder- 网络加密报文。 我们可以把 MessageToByteEncoder 看成网络报文编码器MessageToMessageEncoder 看成业务编码器。 将消息编码为字节 encode(ChannelHandlerContext ctx,I msg,ByteBuf out) encode()方法是你需要实现的唯一抽象方法。它被调用时将会传入要被该类编码为 ByteBuf 的出站消息类型为 I 的。该 ByteBuf 随后将会被转发给 ChannelPipeline 中的下一个ChannelOutboundHandler。
将消息编码为消息 encode(ChannelHandlerContext ctx,I msg,Listout) 这是需要实现的唯一方法。每个通过 write()方法写入的消息都将会被传递给 encode() 方法以编码为一个或者多个出站消息。随后这些出站消息将会被转发给 ChannelPipeline 中的下一个 ChannelOutboundHandler。 编解码器类 Netty 抽象了编解码器类为它们每个都将捆绑一个解码器/编码器对。这些类同时实现了 ChannelInboundHandler 和 ChannelOutboundHandler 接口。
相关的类抽象类 ByteToMessageCodec。抽象类 MessageToMessageCodec。 通过http协议实现SSL/TLS和Web服务
服务端相关代码
public class HttpServer {public static final int port 6789; //设置服务端端口private static EventLoopGroup group new NioEventLoopGroup(); // 通过nio方式来接收连接和处理连接private static ServerBootstrap b new ServerBootstrap();public static final boolean SSL true;/*是否开启SSL模式*//*** Netty创建全部都是实现自AbstractBootstrap。* 客户端的是Bootstrap服务端的则是ServerBootstrap。**/public static void main(String[] args) throws Exception {final SslContext sslCtx;if(SSL){SelfSignedCertificate ssc new SelfSignedCertificate();sslCtx SslContextBuilder.forServer(ssc.certificate(),ssc.privateKey()).build();}else{sslCtx null;}try {b.group(group);b.channel(NioServerSocketChannel.class);b.childHandler(new ServerHandlerInit(sslCtx)); //设置过滤器// 服务器绑定端口监听ChannelFuture f b.bind(port).sync();System.out.println(服务端启动成功,端口是:port);System.out.println(服务器启动模式 ( SSL ? SSL安全模式 :普通模式));// 监听服务器关闭监听f.channel().closeFuture().sync();} finally {group.shutdownGracefully(); //关闭EventLoopGroup释放掉所有资源包括创建的线程}}
}
public class ServerHandlerInit extends ChannelInitializerSocketChannel {private final SslContext sslCtx;public ServerHandlerInit(SslContext sslCtx) {this.sslCtx sslCtx;}Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline ph ch.pipeline();if(sslCtx!null){ph.addLast(sslCtx.newHandler(ch.alloc()));}/*把应答报文 编码*/ph.addLast(encoder,new HttpResponseEncoder());/*把请求报文 解码*/ph.addLast(decoder,new HttpRequestDecoder());/*聚合http为一个完整的报文*/ph.addLast(aggregator,new HttpObjectAggregator(10*1024*1024));/*把应答报文 压缩,非必要*/ph.addLast(compressor,new HttpContentCompressor());ph.addLast(new BusiHandler());}
}
public class BusiHandler extends ChannelInboundHandlerAdapter {/*** 发送的返回值* param ctx 返回* param context 消息* param status 状态*/private void send(ChannelHandlerContext ctx, String context,HttpResponseStatus status) {FullHttpResponse response new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,status,Unpooled.copiedBuffer(context,CharsetUtil.UTF_8));response.headers().set(HttpHeaderNames.CONTENT_TYPE,text/plain;charsetUTF-8);ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);}Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {String result;FullHttpRequest httpRequest (FullHttpRequest)msg;System.out.println(httpRequest.headers());try{//获取路径String pathhttpRequest.uri();//获取bodyString body httpRequest.content().toString(CharsetUtil.UTF_8);//获取请求方法HttpMethod methodhttpRequest.method();System.out.println(接收到:method 请求);//如果不是这个路径就直接返回错误if(!/test.equalsIgnoreCase(path)){result非法请求!path;send(ctx,result,HttpResponseStatus.BAD_REQUEST);return;}//如果是GET请求if(HttpMethod.GET.equals(method)){//接受到的消息做业务逻辑处理...System.out.println(body:body);resultGET请求,应答:RespConstant.getNews();send(ctx,result,HttpResponseStatus.OK);return;}//如果是其他类型请求如postif(HttpMethod.POST.equals(method)){//接受到的消息做业务逻辑处理...//....return;}}catch(Exception e){System.out.println(处理请求失败!);e.printStackTrace();}finally{//释放请求httpRequest.release();}}/** 建立连接时返回消息*/Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println(连接的客户端地址: ctx.channel().remoteAddress());}
}
返回的数据
public class RespConstant {private static final String[] NEWS {helloworld,hellonetty};private static final Random R new Random();public static String getNews(){return NEWS[R.nextInt(NEWS.length)];}
}
启动服务端后访问https://127.0.0.1:6789/test