- pom依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.27.Final</version>
</dependency>
- 后端代码
启动类
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
//监听线程组,主要是监听客户端请求
EventLoopGroup parentGroup = new NioEventLoopGroup();
//工作线程组,主要是处理与客户端的数据通讯。
EventLoopGroup childGroup = new NioEventLoopGroup();
try {
//初始化netty服务器,并且开始监听端口的socket请求
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class).childHandler(new WsServerInitiazer());
ChannelFuture channelFutur = serverBootstrap.bind(8088).sync();
channelFutur.channel().closeFuture().sync();
} finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
初始化类
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
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.stream.ChunkedWriteHandler;
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());
}
}
消息处理类
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;
import java.time.LocalDateTime;
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();
//获取客户端ID
String shortId = ctx.channel().id().asShortText();
System.out.println("服务端接收到客户端消息,客户端ID:" + shortId + ",消息内容:" + text);
clients.stream().forEach(
s-> {
//讲消息发送到对应的客户端
if (shortId.equals(s.id().asShortText())) {
s.writeAndFlush(new TextWebSocketFrame("[服务器接收到消息]"+ LocalDateTime.now()+"--"+text));
}
}
);
}
/*
*客户端打开连接
* */
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
clients.add(channel);
System.out.println("客户端进入,客户端ID:" + channel.id().asShortText());
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
//当触发 这个我们的channelgroup会自动清楚这个
clients.remove(ctx.channel());
System.out.println("客户端离开,客户端ID:" + 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>
- 效果演示
启动NettyServer中main方法
打开两个客户端