项目结构
1.创建启动器
public class WssServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup main = new NioEventLoopGroup();
EventLoopGroup sub = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(main,sub).channel(NioServerSocketChannel.class)
.childHandler(new WsServerInitiazer());
ChannelFuture channelFutur = serverBootstrap.bind(8088).sync();
channelFutur.channel().closeFuture().sync();
} finally {
main.shutdownGracefully();
sub.shutdownGracefully();
}
}
}
2.初始化器
public class WsServerInitiazer extends ChannelInitializer<SocketChannel> {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//websocket基于http协议 所以要有一个http编解码器
pipeline.addLast(new HttpServerCodec());
//对于一个大数据流读写的支持
pipeline.addLast(new ChunkedWriteHandler());
//对于http message进行一些聚合 生成FullHttpRequest huo FullHttpResponse
pipeline.addLast(new HttpObjectAggregator(1024*64));
//====================以上用于支持http支持===========================
// websocket 服务器处理协议 用于指定给客户端连接访问的路由
/*
* 本handler会帮你处理一些繁重复杂的事 会帮你完成握手操作 handshanking(close ping pong)=心跳
* 对于websocket来说 都是以frames来传输的 不同的数据类型对应的framers也不同
* */
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
//添加自定义的助手类
pipeline.addLast(new MessageHandler());
}
}
3.助手类
public class MessageHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
//用于记录和管理channel
private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
//获取客户端传来的信息
String text = msg.text();
System.out.println(text);
clients.stream().forEach(s->s.writeAndFlush(new TextWebSocketFrame("[服务器接收到消息]"+ LocalDateTime.now()+"--"+msg)));
//这个和上面的方法一致
// clients.writeAndFlush(new TextWebSocketFrame("[服务器接收到消息]"+ LocalDateTime.now()+"--"+msg));
}
/*
*客户端打开连接
* */
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
clients.add(channel);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
//当触发 这个我们的channelgroup会自动清楚这个
//clients.remove(ctx.channel());
System.out.println(ctx.channel().id().asLongText());
System.out.println(ctx.channel().id().asShortText());
}
}
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>发送消息:</div>
<input type="text" id="msgContent"/>
<input type="button" value="点我发送" onclick="CHAT.chat()"/>
<div>接受消息:</div>
<div id="receiveMsg" style="background-color: gainsboro;"></div>
<script type="application/javascript">
window.CHAT = {
socket: null,
init: function() {
if (window.WebSocket) {
CHAT.socket = new WebSocket("ws://localhost:8088/ws");
CHAT.socket.onopen = function() {
console.log("连接建立成功...");
},
CHAT.socket.onclose = function() {
console.log("连接关闭...");
},
CHAT.socket.onerror = function() {
console.log("发生错误...");
},
CHAT.socket.onmessage = function(e) {
console.log("接受到消息:" + e.data);
var receiveMsg = document.getElementById("receiveMsg");
var html = receiveMsg.innerHTML;
receiveMsg.innerHTML = html + "<br/>" + e.data;
}
} else {
alert("浏览器不支持websocket协议...");
}
},
chat: function() {
var msg = document.getElementById("msgContent");
CHAT.socket.send(msg.value);
}
};
CHAT.init();
</script>
</body>
</html>