作者:遗留下的痛cc-x_393 | 来源:互联网 | 2023-08-13 15:29
Netty的介绍就不在这里阐述了,前面也写过关于Netty的文章:Netty(一)springboot整合Netty做心跳检测Netty(二)springboot整合netty编写
Netty的介绍就不在这里阐述了,前面也写过关于Netty的文章:
Netty(一) springboot整合Netty做心跳检测
Netty(二) springboot 整合netty编写时间服务器
Netty(三) Netty 之传输文件
这里不做过多的介绍,代码里有相应的注释,
首先添加依赖:
<dependency>
<groupId>io.nettygroupId>
<artifactId>netty-allartifactId>
<version>4.1.21.Finalversion>
dependency>
WebsocketServer
@Component
public class WebsocketServer {
private final static Logger LOGGER = LoggerFactory.getLogger(WebsocketServer.class);
NioEventLoopGroup mainGroup = new NioEventLoopGroup();
NioEventLoopGroup subGroup = new NioEventLoopGroup();
@PostConstruct
public void start() {
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(mainGroup, subGroup)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(9001))
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new WsServerInitializer());
ChannelFuture future = serverBootstrap.bind().sync();
if (future.isSuccess()) {
LOGGER.info("启动 Netty 成功");
}
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@PreDestroy
public void destroy() {
mainGroup.shutdownGracefully().syncUninterruptibly();
subGroup.shutdownGracefully().syncUninterruptibly();
LOGGER.info("关闭 Netty 成功");
}
}
WsServerInitializer(通道初始化)
public class WsServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new HttpServerCodec())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpObjectAggregator(1024 * 64))
.addLast(new WebSocketServerProtocolHandler("/ws"))
.addLast(new ChatHandler());
}
}
ChatHandler(自定义业务处理类)
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
private final static Logger LOGGER = LoggerFactory.getLogger(ChatHandler.class);
private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd hh:MM");
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
String content = textWebSocketFrame.text();
System.out.println("接收到的数据: " + content);
Channel channel = channelHandlerContext.channel();
for (Channel ch : channels) {
if (channel != ch) {
ch.writeAndFlush(new TextWebSocketFrame(sdf.format(new Date()) + ":" + content));
}
}
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
channels.add(ctx.channel());
}
}
chat.html(前端代码)
<body>
<input type="text" id="message">
<input type="button" value="发送消息" onclick="sendMsg()">
<br/>
接收到消息:
<p id="server_message" style="background-color: #AAAAAA">p>
<script>
var websocket = null;
if (window.WebSocket) {
websocket = new WebSocket("ws://127.0.0.1:9001/ws");
websocket.onopen = function (ev) {
console.log("建立连接");
}
websocket.onclose = function (ev) {
console.log("断开连接");
}
websocket.onmessage = function (ev) {
console.log("接收到服务器的消息" + ev.data);
var server_message = document.getElementById("server_message");
server_message.innerHTML += ev.data + "
";
}
} else {
alert("当前浏览器不支持 webSocket")
}
function sendMsg() {
var message = document.getElementById("message");
websocket.send(message.value)
}
script>
body>
案例效果图:
窗口A给窗口B发送消息:
窗口B回复窗口A的消息:
案例项目地址:
netty-chat