Java IO流(五)Netty实战[TCP|Http|心跳检测|Websocket]

Netty入门代码示例(基于TCP服务)

Server端

package com.bierce.io.netty.simple;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.CharsetUtil;
public class NettyServer {public static void main(String[] args) throws InterruptedException {//创建BossGroup和WorkerGroup线程池组,均属于自旋状态EventLoopGroup bossGroup = new NioEventLoopGroup(); //负责连接请求处理EventLoopGroup workerGroup = new NioEventLoopGroup(); //进行业务处理try {//创建服务器端启动,通过链式编程配置相关参数ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //设置为服务端通道.option(ChannelOption.SO_BACKLOG,128) //设置线程队列等待连接的个数.childOption(ChannelOption.SO_KEEPALIVE, true) //设置保持活动连接状态.childHandler(new ChannelInitializer<SocketChannel>() { //匿名创建通道初始对象@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new NettyServerHandler()); //为workerGroup下的NioEventLoop对应管道pipeline设置自定义处理器}});System.out.println("Server is start Successful !!!");ChannelFuture cf = bootstrap.bind(6668).sync(); //绑定指定端口并同步处理cf.channel().closeFuture().sync(); //监听关闭通道方法}finally { //关闭线程池资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //读取客户端发送的数据//ctx:上下文对象,包含管道pipeline,通道等信息//msg:即客户端发送的数据ByteBuf buf = (ByteBuf) msg; //ByteBuf是Netty提供的缓冲区,性能更高System.out.println("客户端发送过来的msg = " + buf.toString((CharsetUtil.UTF_8)));System.out.println("客户端地址 = " + ctx.channel().remoteAddress());}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception { //读取客户端信息完成后进行的业务处理
//        super.channelReadComplete(ctx);ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Client!",CharsetUtil.UTF_8)); //将数据写到缓存并刷新}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close(); //处理异常需要关闭通道}
}

 Client

package com.bierce.io.netty.simple;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.CharsetUtil;
public class NettyClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(); //客户端事件循环组try {Bootstrap bootstrap = new Bootstrap(); //客户端启动对象bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class) //客户端通道.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new NettyClientHandler()); //添加自定义处理器}});System.out.println("Client Start Successful!!!");ChannelFuture sync = bootstrap.connect("127.0.0.1", 6668).sync();sync.channel().closeFuture().sync(); //监听关闭通道}finally {eventLoopGroup.shutdownGracefully();}}
}
class NettyClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception { //通道就绪会触发该方法ctx.writeAndFlush(Unpooled.copiedBuffer("Hello, Server!", CharsetUtil.UTF_8)); //将数据写到缓存并刷新}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //读取服务端返回信息ByteBuf buf = (ByteBuf) msg; //ByteBuf是Netty提供的缓冲区,性能更高System.out.println("服务端发送过来的msg = " + buf.toString((CharsetUtil.UTF_8)));System.out.println("服务端地址 = " + ctx.channel().remoteAddress());}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close(); //处理异常需要关闭通道}
}

运行结果

Server
Client

Netty入门代码示例(基于HTTP服务)

package com.bierce.io.netty.http;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;import java.net.URI;public class TestServer {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workerGroup = new NioEventLoopGroup();try {//创建服务器端启动,通过链式编程配置相关参数ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //设置为服务端通道.childHandler(new TestServerInitializer()); //设置为自定义的初始化System.out.println("Server is start Successful !!!");ChannelFuture cf = bootstrap.bind(9999).sync(); //绑定指定端口并同步处理cf.channel().closeFuture().sync(); //监听关闭通道方法}finally { //关闭线程池资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
class TestServerInitializer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();//HttpServerCodec是Netty提供的处理Http的编-解码器 使用io.netty:netty-all:4.1.20Final版本,其他版本不支持会报错pipeline.addLast("MyHttpServerCodec", new HttpServerCodec());//增加自定义的handlerpipeline.addLast("MyTestHttpServerHandler", new TestHttpServerHandler());}
}
class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {//读取客户端数据@Overrideprotected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {if (httpObject instanceof HttpRequest){System.out.println("httpObject Type = " + httpObject.getClass());System.out.println("Client Address = " + channelHandlerContext.channel().remoteAddress());//对特定资源进行过滤HttpRequest httpRequest = (HttpRequest)httpObject;URI uri = new URI(httpRequest.getUri());if ("/favicon.ico".equals(uri.getPath())){System.out.println("favicon.ico资源不做响应");return;}//回复浏览器信息(http协议)ByteBuf content = Unpooled.copiedBuffer("Hello, I'm Server", CharsetUtil.UTF_8);FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());channelHandlerContext.writeAndFlush(response);}}
}

运行结果

Netty心跳检测机制

package com.bierce.io.netty.heartbeat;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
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;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;import java.util.concurrent.TimeUnit;
public class MyServer {public static void main(String[] args) {NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//IdleStateHandler:Netty提供的处理空闲状态的处理器//readerIdleTime:多长时间没有读操作,会发送心跳检测包检测是否连接//writerIdleTime:多长时间没有写操作,会发送心跳检测包检测是否连接//allIdleTime:多长时间没有读写操作,会发送心跳检测包检测是否连接pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));//IdleStateHandler触发后,将传递给下一个Handler的userEventTriggered方法去处理//通过自定义的Handler对空闲状态进一步处理pipeline.addLast(new MyServerHandler());}});ChannelFuture sync = bootstrap.bind(9999).sync().channel().closeFuture().sync();} catch (InterruptedException e) {throw new RuntimeException(e);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
class MyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {if (evt instanceof IdleStateEvent){IdleStateEvent IdleStateEvent = (IdleStateEvent) evt;String eventType = null;switch (IdleStateEvent.state()){case READER_IDLE:eventType = "读空闲";break;case WRITER_IDLE:eventType = "写空闲";break;case ALL_IDLE:eventType = "读写空闲";break;}System.out.println(ctx.channel().remoteAddress() + "-已超时,超时类型为: " + eventType );System.out.println("Server will deal with it instantly...");//发生空闲则关闭当前通道ctx.close();}}
}
class NettyClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(); //客户端事件循环组try {Bootstrap bootstrap = new Bootstrap(); //客户端启动对象bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class) //客户端通道.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new NettyClientHandler()); //添加自定义处理器}});System.out.println("Client Start Successful!!!");ChannelFuture sync = bootstrap.connect("127.0.0.1", 9999).sync();sync.channel().closeFuture().sync(); //监听关闭通道}finally {eventLoopGroup.shutdownGracefully();}}
}

 注意: 需要调整readerIdleTime|writerIdleTime|allIdleTime参数才会显示对应超时信息

Netty入门代码示例(基于WebSocket协议)

服务端

package com.bierce.websocket;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;import java.time.LocalDateTime;public class MyWebsocketServer {public static void main(String[] args) {NioEventLoopGroup bossGroup = new NioEventLoopGroup();NioEventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//基于Http协议,所以需要http解码编码pipeline.addLast(new HttpServerCodec());pipeline.addLast(new ChunkedWriteHandler()); //处理块方式的写操作//http传输过程数据量非常大时会分段,而HttpObjectAggregator可以将多个分段聚合pipeline.addLast(new HttpObjectAggregator(8192));//webSocket采用帧方式传输数据//WebSocketServerProtocolHandler作用是将http协议升级为ws协议,且保持长连接pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));pipeline.addLast(new MyWebsocketServerHandler());}});ChannelFuture sync = bootstrap.bind(9999).sync().channel().closeFuture().sync();} catch (InterruptedException e) {throw new RuntimeException(e);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}
class MyWebsocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {System.out.println("Server receive the Info: " + msg.text());ctx.channel().writeAndFlush(new TextWebSocketFrame("Server time " + LocalDateTime.now() + " --- " + msg.text()));}@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {System.out.println("有客户端连接成功 --" + ctx.channel().id().asLongText()); //asLongText唯一值}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {System.out.println("有客户端已经离开 --" + ctx.channel().id().asLongText()); //asLongText唯一值}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {System.out.println("异常Info:" + cause.getMessage());ctx.close();}
}

客户端(浏览器)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Websocket</title>
</head>
<body>
<script>var socket;if (window.WebSocket) {socket = new WebSocket("ws://localhost:9999/hello");//相当于channelRead0,读取服务器端的消息socket.onmessage = function(ev){var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + ev.data;}//开启连接socket.onopen = function(ev){var rt = document.getElementById("responseText");rt.value = "开启连接成功!";}//连接关闭socket.onclose = function(ev){var rt = document.getElementById("responseText");rt.value = rt.value + "\n" + "连接关闭成功!";}}//发送消息给服务器function send(msg){if(!window.socket){ //是否已创建socketreturn;}if(socket.readyState == WebSocket.OPEN){socket.send(msg);}else{alert("socket未连接");}}
</script><form onsubmit="return false"><textarea name="message" style="height:300px;width:300px"></textarea><input type="button" value="Send" onclick="send(this.form.message.value)"><textarea id="responseText" style="height:300px;width:300px"></textarea><input type="button" value="Clear" onclick="document.getElementById('responseText').value=''"></form>
</body>
</html>

效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/102768.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用动态IP是否会影响网络

今天我们要谈论的话题是关于动态IP和网络的关系。也许有些小伙伴对这个概念还比较陌生&#xff0c;但别担心&#xff0c;我会简单明了的给你理清楚。让我们一起看看动态IP到底能否影响到网络。 首先&#xff0c;我们先来搞明白什么是动态IP。在互联网世界中&#xff0c;每一个连…

跨越边界:从前端切图仔走进iOS开发(Swift版--上集)

本文简介 点赞 关注 收藏 学会了 本文将以前端开发者的视角&#xff0c;和各位工友进入iOS开发的世界。 本文以实战为导向&#xff0c;快速掌握iOS开发这个技能。 无论你是想要扩展技能领域&#xff0c;还是对iOS开发充满好奇&#xff0c;花一个下午学习本文都能打开iOS开…

【consul】

consul 一、什么是服务注册与发现1.11.2 二、 什么是consul2.1定义2.2特性2.2.1服务注册与发现&#xff1a;2.2.2健康检查&#xff1a;2.2.3Key/Value存储&#xff1a; 三、consul部署-datacenter &#xff1a;指定数据中心名称&#xff0c;默认是dc1。consul &#xff1a;指定…

flask获取请求对象的get和post参数

前言 get请求参数是在URL里面的&#xff0c;post请求参数是放在请求头里面的 get请求&#xff1a; index_page.route("/get") def get():var_a request.args.get("a", "jarvis")return "request:%s,params:%s,var_a:%s" %(request…

接口自动化如何封装mysql操作

数据查询类封装 1. 功能分析 可以连接不同sql数据库查一条数据&#xff0c;多条数据可以获取不同格式的数据 2. 封装成数据库查询类 封装思路: 数据库查询模块有多个功能&#xff0c;且需要复用&#xff0c;所以封装成类创建对象方法实现各种查询在构造方法中创建连…

Word中对象方法(Methods)的理解及示例(上)

【分享成果&#xff0c;随喜正能量】奋斗没有终点,任何时候都是一个起点&#xff0c;沉潜是为了蓄势待发&#xff0c;沉潜是为了等待因缘。鲸豚沉潜于大海&#xff0c;幽兰深藏于山谷&#xff0c;能够经得起沉潜的人&#xff0c;才会有更高的成就。正如一年的树木只能当柴烧&am…

基于Jenkins自动打包并部署docker环境

目录 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.200.111 git git服务器 CentOS7.5 192.168.200.112 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168…

TCP最大连接数问题总结

最大TCP连接数量限制有&#xff1a;可用端口号数量、文件描述符数量、线程、内存、CPU等。每个TCP连接都需要以下资源&#xff0c;如图所示&#xff1a; 1、可用端口号限制 Q&#xff1a;一台主机可以有多少端口号&#xff1f;端口号与TCP连接&#xff1f;是否能修改&#x…

Wireshark数据抓包分析之互联网协议(IP协议)

一、实验目的&#xff1a; 通过wireshark抓包分析IP协议的具体内容 二、预备知识&#xff1a; 1.IP地址存在的意义&#xff0c;就是为了弥补mac地址的不足&#xff0c;用于区分不同的网络 2.还有一些ip协议、ip数据包这些东西 三、网络拓扑 四、实验过程&#xff1a; part1&…

Docker容器与虚拟化技术:Gitlab账户注册

目录 一、实验 1.gitlab 一、实验 1.gitlab (1) 概念 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。 &#xff08;2&#xff09;官网 The DevSecOps Platform | GitLab &#xff08;3&#…

OpenAI推出GPT-3.5Turbo微调功能并更新API;Midjourney更新局部绘制功能

&#x1f989; AI新闻 &#x1f680; OpenAI推出GPT-3.5Turbo微调功能并更新API&#xff0c;将提供GPT-4微调功能 摘要&#xff1a;OpenAI宣布推出GPT-3.5Turbo微调功能&#xff0c;并更新API&#xff0c;使企业和开发者能够定制ChatGPT&#xff0c;达到或超过GPT-4的能力。通…

uniapp - 实现卡片式胶囊单选后右上角出现 “√“ 对勾对号选中效果功能,适用于小程序h5网页app全平台通用(一键复制组件源码,开箱即用!)

效果图 uniapp全平台兼容(小程序/h5网页/app)实现点击选择后,右上角出现 √ 对号效果(角标形式展现),功能组件, 改个样式,直接复制使用该组件。 组件源码 在 components 组件文件夹下,随便建立一个 .vue 文件,一键复制下方源码。

Centos7查看磁盘和CUP统计信息iostat命令

Centos7查看磁盘和CUP统计信息iostat命令 Centos7内存高|查看占用内存命令 docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六…

如何在App里拉起小程序?

什么是小程序运行时框架&#xff1f; FinClip 的小程序编程模型是分为多个页面&#xff0c;每个页面有自己的 template、CSS 和 JS&#xff0c;实际在运行的时候&#xff0c;业务逻辑的 JS 代码是运行在独立的 JavaScript 引擎中&#xff0c;每个页面的 template 和 CSS 是运行…

vue组件的scope 以及 如何样式穿透

个人复习&#xff01;&#xff01;&#xff01; 有什么用 让当前组件的样式不会修改到其它地方的样式&#xff0c;使用了data-v-hash的方式来使css有了它对应模块的标识 实现原理 1、给HTML的dom节点添加一个不重复的data属性(例如: data-v-5558831a)来唯一标识这个dom 元素…

Linux下彻底卸载jenkins

文章目录 1、停服务进程2、查找安装目录3、删掉相关目录4、确认已完全删除 1、停服务进程 查看jenkins服务是否在运行&#xff0c;如果在运行&#xff0c;停掉 ps -ef|grep jenkins kill -9 XXX2、查找安装目录 find / -name "jenkins*"3、删掉相关目录 # 删掉相…

Prompt本质解密及Evaluation实战(一)

一、基于evaluation的prompt使用解析 基于大模型的应用评估与传统应用程序的评估不太一样&#xff0c;特别是基于GPT系列或者生成式语言模型&#xff0c;因为模型生成的内容与传统意义上所说的内容或者标签不太一样。 以下是借用了ChatGPT官方的evaluation指南提出的对结果的具…

【负载均衡】Nacos简单入门

Nacos简单入门 快速安装 在Nacos的GitHub页面&#xff0c;提供有下载链接&#xff0c;可以下载编译好的Nacos服务端或者源代码&#xff1a; 下载完压缩包之后&#xff0c;放在任意目录下面进行解压&#xff1a; GitHub主页&#xff1a;https://github.com/alibaba/nacos G…

MyBatid动态语句且模糊查询

目录 什么是MyBtais动态语句&#xff1f;&#xff1f;&#xff1f; MyBatis常用的动态标签和表达式 if标签 Choose标签 where标签 MyBatis模糊查询 #与$的区别 ​编辑 MyBatis映射 resultType resultMap 什么是MyBtais动态语句&#xff1f;&#xff1f;&#xff1f;…

2.IO控制器

第五章 I/O管理 2.I/O控制器 I/O控制器的组成&#xff1a; I/O控制器负责接收和识别从CPU发来的各种命令&#xff0c;同时需要翻译为具体的设备可以明白的命令&#xff0c;通过控制器与设备的接口发送给具体的设备&#xff0c;让设备执行相应的操作。 一个I/O控制器有可能会负…