Netty笔记(4)-对Http和WebSocket的支持、心跳检测机制

更新时间:2023-06-07 20:47:49 阅读: 评论:0

Netty笔记(4)-对Http和WebSocket的⽀持、⼼跳检测机制对HTTP的⽀持
服务端代码:
向 PipeLine中注册 HttpServerCodec Http协议的编码解码⼀体的Handler 处理Http请求封装Http响应
public class TestServer {
anaesthesiapublic static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap rverBootstrap = new ServerBootstrap();
.channel(NioServerSocketChannel.class)
.
childHandler(new ChannelInitializer<SocketChannel>{
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//向管道加⼊处理器
//得到管道
ChannelPipeline pipeline = ch.pipeline();
//加⼊⼀个netty 提供的httpServerCodec codec =>[coder - decoder]
//HttpServerCodec 说明翻译资格考试
//1. HttpServerCodec 是netty 提供的处理http的编-解码器
pipeline.addLast("MyHttpServerCodec",new HttpServerCodec());
//2. 增加⼀个⾃定义的handler
pipeline.addLast("MyTestHttpServerHandler", new TestHttpServerHandler());
System.out.println("ok~~~~");如何提高阅读速度
}
});
ChannelFuture channelFuture = rverBootstrap.bind(6668).sync();
channelFuture.channel().cloFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
⾃定义Handler:
过滤浏览器请求 favicon.ico 的请求并回送信息
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
//channelRead0 读取客户端数据
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
System.out.println("对应的channel=" + ctx.channel() + " pipeline=" + ctx
.pipeline() + " 通过pipeline获取channel" + ctx.pipeline().channel());
System.out.println("当前ctx的handler=" + ctx.handler());
//判断 msg 是不是 httprequest请求
if(msg instanceof HttpRequest) {
System.out.println("msg 类型=" + Class());
System.out.println("客户端地址" + ctx.channel().remoteAddress());
//获取到
HttpRequest httpRequest = (HttpRequest) msg;
//获取uri, 过滤指定的资源
URI uri = new URI(httpRequest.uri());
if("/favicon.ico".Path())) {
System.out.println("请求了 favicon.ico, 不做响应");
return;
}
/
/回复信息给浏览器 [http协议]
ByteBuf content = piedBuffer("hello, 我是服务器", ChartUtil.UTF_8);
//构造⼀个http的相应,即 httprespon
FullHttpRespon respon = new DefaultFullHttpRespon(HttpVersion.HTTP_1_1, HttpResponStatus.OK, content);
respon.headers().t(HttpHeaderNames.CONTENT_TYPE, "text/plain");
respon.headers().t(HttpHeaderNames.CONTENT_LENGTH, adableBytes());
//将构建好 respon返回
ctx.writeAndFlush(respon);
}
}
}
浏览器地址栏输⼊连接服务端并收到服务端信息
对WebSocket 的⽀持
服务端代码:
添加将Http协议升级为 webSocket协议的拦截器 WebSocketServerProtocolHandler 并指定路径
public class MyServer {
public static void main(String[] args) throws Exception{
//创建两个线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLoop
try {
ServerBootstrap rverBootstrap = new ServerBootstrap();
rverBootstrap.channel(NioServerSocketChannel.class);
rverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
rverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//因为基于http协议,使⽤http的编码和解码器
pipeline.addLast(new HttpServerCodec());
//是以块⽅式写,添加ChunkedWriteHandler处理器
pipeline.addLast(new ChunkedWriteHandler());
/
*
说明
1. http数据在传输过程中是分段, HttpObjectAggregator ,就是可以将多个段聚合
2. 这就就是为什么,当浏览器发送⼤量数据时,就会发出多次http请求
*/
pipeline.addLast(new HttpObjectAggregator(8192));
/*
说明
1. 对应websocket ,它的数据是以帧(frame) 形式传递
2. 可以看到WebSocketFrame 下⾯有六个⼦类
3. 浏览器请求时 ws://localhost:7000/hello 表⽰请求的uri
4. WebSocketServerProtocolHandler 核⼼功能是将 http协议升级为 ws协议 , 保持长连接
*/
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
//⾃定义的handler ,处理业务逻辑
pipeline.addLast(new MyTextWebSocketFrameHandler());
}
});
//启动服务器
ChannelFuture channelFuture = rverBootstrap.bind(7000).sync();
channelFuture.channel().cloFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
服务端Handler:
websocket 协议中传输数据为数据帧 (TextWebSocketFrame)
//这⾥ TextWebSocketFrame 类型,表⽰⼀个⽂本帧(frame)
public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>{
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("服务器收到消息 " + ());
//回复消息
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间" + w() + " " + ()));    }
//当web客户端连接后,触发⽅法
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
//id 表⽰唯⼀的值,LongText 是唯⼀的 ShortText 不是唯⼀
System.out.println("handlerAdded 被调⽤" + ctx.channel().id().asLongText());
System.out.println("handlerAdded 被调⽤" + ctx.channel().id().asShortText());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerRemoved 被调⽤" + ctx.channel().id().asLongText());
}
期望值@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cau) throws Exception {
System.out.println("异常发⽣ " + Message());
ctx.clo(); //关闭连接
}
}
前端html:
可以给客户端发送信息可以接受客户端信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta chart="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var socket;
/
/判断当前浏览器是否⽀持websocket
if(window.WebSocket) {
socket = new WebSocket("ws://localhost:7000/hello");
//相当于channelReado, ev 收到服务器端回送的消息
var rt = ElementById("responText");
rt.value = rt.value + "\n" + ev.data;
}
//相当于连接开启(感知到连接开启)
萨达姆侯赛因
var rt = ElementById("responText");
rt.value = "连接开启了.."
}
//相当于连接关闭(感知到连接关闭)
var rt = ElementById("responText");
rt.value = rt.value + "\n" + "连接关闭了.."
}
} el {
alert("当前浏览器不⽀持websocket")
}
//发送消息到服务器
两小儿辩日翻译
function nd(message) {
if(!window.socket) { //先判断socket是否创建好
return;
}
adyState == WebSocket.OPEN) {
//通过socket 发送消息
socket.nd(message)
} el {
alert("连接没有开启");
}
}
</script>
<form onsubmit="return fal">
<textarea name="message" ></textarea>
<input type="button" value="发⽣消息" onclick="nd(ssage.value)">
<textarea id="responText" ></textarea>
<input type="button" value="清空内容" onclick="ElementById('responText').value=''">
</form>
恋爱学分</body>
</html>
Netty 的⼼跳检测机制
向pipeLine中加⼊⼼跳检测的Handler ,监听读空闲写空闲读写空闲,并设置时间.,如果在设定时间内没有发⽣读写事件, 则会产⽣⼀个相关事件,并传递到下⼀个 Handler 中 (⾃定义处理Handler)
服务端代码:
⼼跳检测Handler 在监听到相应的事件后会交由注册的下⼀个Handler的urEventTriggered⽅法处理 ,这⾥注册⼀个⾃定义Handler
小学数学概念教学public class MyServer {
public static void main(String[] args) throws Exception{
//创建两个线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLoop
try {
ServerBootstrap rverBootstrap = new ServerBootstrap();
rverBootstrap.channel(NioServerSocketChannel.class);
rverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
rverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
hiroki@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//加⼊⼀个netty 提供 IdleStateHandler
/*
说明
1. IdleStateHandler 是netty 提供的处理空闲状态的处理器
2. long readerIdleTime : 表⽰多长时间没有读, 就会发送⼀个⼼跳检测包检测是否连接
3. long writerIdleTime : 表⽰多长时间没有写, 就会发送⼀个⼼跳检测包检测是否连接
4. long allIdleTime : 表⽰多长时间没有读写, 就会发送⼀个⼼跳检测包检测是否连接
*                  5. 当 IdleStateEvent 触发后 , 就会传递给管道的下⼀个handler去处理
*                  通过调⽤(触发)下⼀个handler 的 urEventTiggered , 在该⽅法中去处理 IdleStateEvent(读空闲,写空闲,读写空闲)                    */
pipeline.addLast(new IdleStateHandler(7000,7000,10, TimeUnit.SECONDS));
//加⼊⼀个对空闲检测进⼀步处理的handler(⾃定义)
pipeline.addLast(new MyServerHandler());
}
});
//启动服务器
ChannelFuture channelFuture = rverBootstrap.bind(7000).sync();
channelFuture.channel().cloFuture().sync();
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
finish处理事件的Handler (urEventTriggered⽅法中处理) :
public class MyServerHandler extends ChannelInboundHandlerAdapter {
/**
*
* @param ctx 上下⽂
* @param evt 事件
* @throws Exception
*/
@Override
public void urEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if(evt instanceof IdleStateEvent) {
//将  evt 向下转型 IdleStateEvent
IdleStateEvent event = (IdleStateEvent) evt;
String eventType = null;
switch (event.state()) {
ca READER_IDLE:
eventType = "读空闲";
break;
ca WRITER_IDLE:
eventType = "写空闲";
break;
ca ALL_IDLE:
eventType = "读写空闲";
break;
}
System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType);
System.out.println("服务器做相应处理..");
/
/如果发⽣空闲,我们关闭通道
// ctx.channel().clo();
}
}
}

本文发布于:2023-06-07 20:47:49,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/137405.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:连接   空闲   检测   协议   处理   客户端   浏览器   请求
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图