网络I/o编程模型18 netty通过websocket实现服务,客户端通信
Posted 健康平安的活着
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络I/o编程模型18 netty通过websocket实现服务,客户端通信相关的知识,希望对你有一定的参考价值。
一 需求描述
基于websocket的全双工的长连接,实现客户端和服务端之间信息的交互。比如客户端浏览器和服务器会相互感知,比如服务器关闭了,浏览器会感知;同样浏览器关闭了,服务器也会感知。
二 代码实现
1.服务端
package com.ljf.netty.netty.websocket;
import com.ljf.netty.netty.heartbeat.MyServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
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 io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: NettyWebSocketServer
* @Description: TODO
* @Author: liujianfu
* @Date: 2022/06/04 12:00:07
* @Version: V1.0
**/
public class NettyWebSocketServer
public static void main(String[] args)
//创建两个线程组
EventLoopGroup bossGroup=new NioEventLoopGroup(1);
EventLoopGroup workerGroup=new NioEventLoopGroup();//8个NioEventLoop
try
ServerBootstrap serverBootstrap=new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
serverBootstrap.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());
//当浏览器发送大量数据时,就会发出多次http请求,http数据在传输过程中是分段的。
pipeline.addLast(new HttpObjectAggregator(8192));
//websocket 它的数据是以帧的形式传递;WebSocketSeverProtocolHandler 核心功能是将http协议升级为ws协议,保持长连接
//浏览器请求是,ws://localhost:6000/hello 表示请求的uri
pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
//自定义的handler,处理业f务逻辑
pipeline.addLast(new MyTextWebSocketFrameHandler());
);
//启动服务器
ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1",6666).sync();
channelFuture.channel().closeFuture().sync();
catch (InterruptedException e)
e.printStackTrace();
finally
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
2.自定义处理类
package com.ljf.netty.netty.websocket;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import java.time.LocalDateTime;
/**
* @ClassName: MyTextWebSocketFrameHandler
* @Description: TODO 这里的TextWebSocketFrame 表示类型,表示一个文本帧
* @Author: liujianfu
* @Date: 2022/06/04 16:36:39
* @Version: V1.0
**/
public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame>
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception
System.out.println("服务器收到的信息:"+msg.text());
//回复信息
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:"+ LocalDateTime.now()+""+msg.text()));
//有web客户端连接后,触发的方法
public void handlerAdded(ChannelHandlerContext ctx)
//id 表示唯一的值,LongText是唯一的; shortText不是唯一
System.out.println("handlerAdded 被调用:"+ctx.channel().id().asLongText());
System.out.println("handlerAdded 被调用:"+ctx.channel().id().asShortText());
//有web客户端连接断开后,触发的方法
public void handlerRemoved(ChannelHandlerContext ctx)
System.out.println("handlerRemove 被调用:"+ctx.channel().id().asLongText());
//发生异常
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause)
System.out.println("异常发生:"+cause.getMessage());
ctx.close();
3. 前端页面
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
<script>
var socket;
//判断当前浏览器是否支持websocket
if(window.WebSocket)
socket=new WebSocket("ws://127.0.0.1:6666/hello");
//相当于channelReado,ev收到的服务器回送的消息
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"+" 连接关闭了....";
else
alert("当前浏览器不支持websocket");
//发送消息道服务器
function sendInfo(message)
alert(message);
if(!window.socket)
return ; //先判断socket是否创建好
if(socket.readyState==WebSocket.OPEN)
//通过socket发送消息
socket.send(message);
else
alert("连接没有开启...");
</script>
</head>
<body>
<form onsubmit="return false">
<textarea name="message" style="height:300px;width:300px"></textarea>
<input type="button" value="发送消息" onclick="sendInfo(this.form.message.value)">
<textarea id="responseText" style="height:300px;width:300px"></textarea>
<input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''">
</form>
</body>
</html>
4.查询结果
1.服务端
2.页面
以上是关于网络I/o编程模型18 netty通过websocket实现服务,客户端通信的主要内容,如果未能解决你的问题,请参考以下文章