当前位置: 代码迷 >> 综合 >> Netty4 + WebSocket 实现网页版聊天室
  详细解决方案

Netty4 + WebSocket 实现网页版聊天室

热度:36   发布时间:2023-11-30 19:39:18.0

网页聊天室效果展示:

 

 

① Netty依赖

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.32.Final</version>
</dependency>

 

② Netty的服务端:定义NettyServer,让其支持Websocket通信,并添加自己的请求处理器

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
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;public class NettyServer {private int port;public NettyServer(int port) {this.port = port;}public void start() {// 创建服务类ServerBootstrap sb = new ServerBootstrap();// 创建boss和wokerNioEventLoopGroup boss = new NioEventLoopGroup();NioEventLoopGroup woker = new NioEventLoopGroup();try {// 设置线程池sb.group(boss, woker);// 设置channel工厂sb.channel(NioServerSocketChannel.class);// 设置管道sb.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new HttpServerCodec());// websocket基于http协议,需要HttpServerCodecch.pipeline().addLast(new HttpObjectAggregator(65535)); // http消息组装ch.pipeline().addLast(new WebSocketServerProtocolHandler("/ws")); // websocket通信支持ch.pipeline().addLast(new MyServerHandler()); // 自定义处理器}});// 服务器异步创建绑定ChannelFuture cf = sb.bind(port).sync();// 等待服务端关闭cf.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {boss.shutdownGracefully();woker.shutdownGracefully();}}/*** server启动* @param args*/public static void main(String[] args) {new NettyServer(1234).start();}
}

③ 自定义监听Channel的处理器

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;public class MyServerHandler extendsSimpleChannelInboundHandler<TextWebSocketFrame> {public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);/*** 监听客户端注册*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {// 新客户端连接,通知其他客户端for (Channel channel : channels) {String msg = "<font color='red'>~~用户"+ ctx.channel().remoteAddress() + "上线~~<font>";channel.writeAndFlush(msgPot(msg));}// 加入队列channels.add(ctx.channel());}/*** 监听客户端断开*/@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {// 离开时,通知其他客户端for (Channel channel : channels) {if (channel != ctx.channel()) {String msg = "<font color='red'>~~用户"+ ctx.channel().remoteAddress() + "离开~~<font>";channel.writeAndFlush(msgPot(msg));}}// 整理队列channels.remove(ctx.channel());}/*** 读取客户端发过来的消息*/@Overridepublic void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame tmsg)throws Exception {// 处理消息for (Channel channel : channels) {// 判断是否是当前用户的消息if (channel != ctx.channel()) {String msg = "[用户" + channel.remoteAddress() + " 说:]"+ tmsg.text();channel.writeAndFlush(msgPot(msg));} else {String msg = "[我说:]" + tmsg.text();channel.writeAndFlush(msgPot(msg));}}}/*** 监听连接异常*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception {ctx.close(); // 关闭}/*** 封装消息* * @param msg* @return*/public TextWebSocketFrame msgPot(String msg) {return new TextWebSocketFrame(msg);}}

 

至此,服务端的代码就已经结束了,下面开始书写页面客户端代码

 

④ netty.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>netty聊天室</title>
<style>
.webchat {position: absolute;top: 15%;left: 35%;text-align: center;
}#content {width: 345px;height: 345px;border-left: 1px solid #AAAAAA;border-right: 1px solid #AAAAAA;border-top: 2px solid #AAAAAA;border-bottom: 2px solid #AAAAAA;border-radius: 2px;margin: 9px 0;overflow: auto;
}.button {background: #60F49B;color: #ffffff;border: none;height: 30px;
}#msg {height: 25px;
}
</style><!-- jquery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</head>
<body><div class="webchat"><div class="title">Netty4+Websocket聊天室</div><div id="content"></div><input type="text" id="msg" /> <input class="button" type="button"value="发送消息" onclick="CHAT.chat()" /> <input class="button"type="button" value="清空聊天记录" onclick="CHAT.clean()" /></div>
</body><script type="text/javascript">window.CHAT = {socket : null,init : function() {if (window.WebSocket) {// ws://机器地址:netty绑定的端口/服务端定义socket路径CHAT.socket = new WebSocket("ws://192.168.1.126:1234/ws");CHAT.socket.onopen = function() {console.log("连接成功");}, CHAT.socket.onclose = function() {console.log("连接关闭");}, CHAT.socket.onerror = function() {console.log("异常");}, CHAT.socket.onmessage = function(e) {var htm = $("#content").html();$("#content").html(htm + "<br>" + e.data)}} else {alert("浏览器不支持websocket协议.....");}},chat : function() {if ($("#msg").val() != "")CHAT.socket.send($("#msg").val());},clean : function() {$("#content").html("")}}CHAT.init();
</script>
</html>

 

tip:web项目和Netty服务的启动问题

① 先执行NettyServer的main方法,开启NettyServer。然后tomcat启动web项目,访问netty.jsp。

② web项目中启动时创建一个线程去启动Netty服务,访问netty.jsp

 

参考博客:https://www.jianshu.com/p/0b2772f5778c

  相关解决方案