package com.cetcnav.nioWebSocket;
import com.cetcnav.base.utils.PropertiesUtils;
import cn.hutool.core.lang.Console;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
public class NioWebSocketServer implements Runnable {
@Override
public void run() {
init();
}
private final static Integer port = PropertiesUtils.getInteger("nio.wensocket.port");
public void init(){
Console.log("正在启动websocket服务器");
NioEventLoopGroup boss=new NioEventLoopGroup();
NioEventLoopGroup work=new NioEventLoopGroup();
try {
ServerBootstrap bootstrap=new ServerBootstrap();
bootstrap.option(ChannelOption.SO_BACKLOG, 1024);
bootstrap.childOption(ChannelOption.SO_KEEPALIVE,true);
bootstrap.group(boss,work).localAddress(port);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new NioWebSocketChannelInitializer());
Channel channel = bootstrap.bind().sync().channel();
Console.log("webSocket服务器启动成功:"+channel);
channel.closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
Console.error("运行出错:"+e);
}finally {
boss.shutdownGracefully();
work.shutdownGracefully();
Console.log("websocket服务器已关闭");
}
}
public static void main(String[] args) {
new NioWebSocketServer().init();
}
}
package com.cetcnav.nioWebSocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.CharsetUtil;
import java.util.Date;
import cn.hutool.core.lang.Console;
import static io.netty.handler.codec.http.HttpUtil.isKeepAlive;
public class NioWebSocketHandler extends SimpleChannelInboundHandler<Object> {
private WebSocketServerHandshaker handshaker;
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
Console.log("收到消息:"+msg);
if (msg instanceof FullHttpRequest){
handleHttpRequest(ctx, (FullHttpRequest) msg);
}else if (msg instanceof WebSocketFrame){
handlerWebSocketFrame(ctx, (WebSocketFrame) msg);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Console.log("客户端加入连接:"+ctx.channel());
ChannelHandlerPool.addChannel(ctx.channel());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Console.log("客户端断开连接:"+ctx.channel());
ChannelHandlerPool.removeChannel(ctx.channel());
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
private void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame){
if (frame instanceof CloseWebSocketFrame) {
handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain());
return;
}
if (frame instanceof PingWebSocketFrame) {
ctx.channel().write(
new PongWebSocketFrame(frame.content().retain()));
return;
}
if (!(frame instanceof TextWebSocketFrame)) {
Console.log("本例程仅支持文本消息,不支持二进制消息");
throw new UnsupportedOperationException(String.format(
"%s frame types not supported", frame.getClass().getName()));
}
String request = ((TextWebSocketFrame) frame).text();
Console.log("服务端收到:" + request);
TextWebSocketFrame tws = new TextWebSocketFrame(new Date().toString()
+ ctx.channel().id() + ":" + request);
ctx.channel().writeAndFlush(tws);
}
private void handleHttpRequest(ChannelHandlerContext ctx,FullHttpRequest req) {
if (!req.decoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
return;
}
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory("", null, false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
} else {
handshaker.handshake(ctx.channel(), req);
}
}
private static void sendHttpResponse(ChannelHandlerContext ctx,
FullHttpRequest req, DefaultFullHttpResponse res) {
if (res.status().code() != 200) {
ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(),
CharsetUtil.UTF_8);
res.content().writeBytes(buf);
buf.release();
}
ChannelFuture f = ctx.channel().writeAndFlush(res);
if (!isKeepAlive(req) || res.status().code() != 200) {
f.addListener(ChannelFutureListener.CLOSE);
}
}
}
package com.cetcnav.nioWebSocket;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
public class ChannelHandlerPool {
private static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
private static ConcurrentMap<String, ChannelId> ChannelMap=new ConcurrentHashMap<String, ChannelId>();
public static Set<Channel> channelGroup = Collections.synchronizedSet(new HashSet<>());
public static void addChannel(Channel channel){
group.add(channel);
ChannelMap.put(channel.id().asShortText(),channel.id());
}
public static void removeChannel(Channel channel){
group.remove(channel);
ChannelMap.remove(channel.id().asShortText());
String channelId = channel.id().asShortText();
Iterator<Channel> it = channelGroup.iterator();
while(it.hasNext()){
Channel data = it.next();
String removeString = data.id().asShortText();
if (channelId.equals(removeString)){
it.remove();
}
}
}
public static Channel findChannel(String id){
return group.find(ChannelMap.get(id));
}
public static void send2All(TextWebSocketFrame tws){
group.writeAndFlush(tws);
}
public static String sendMessage(String parkId, String message){
List<Channel> channelList = getChannelByName(parkId);
if (channelList.size() <= 0) {
return "parkId" + parkId + "不在线!";
}
ByteBuf byteBuf = Unpooled.copiedBuffer(message.getBytes());
channelList.forEach(channel -> channel.writeAndFlush(new TextWebSocketFrame(message)));
return "success";
}
public static List<Channel> getChannelByName(String parkId) {
AttributeKey<String> key = AttributeKey.valueOf("parkId");
return ChannelHandlerPool.channelGroup.stream().filter(channel -> channel.attr(key).get().equals(parkId))
.collect(Collectors.toList());
}
}
package com.cetcnav.worker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.cetcnav.cacheManage.MessageCahce;
import com.cetcnav.nioWebSocket.ChannelHandlerPool;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class SendMessage2WebWorker implements Runnable {
private static Logger log = LoggerFactory.getLogger(SendMessage2WebWorker.class);
@Override
public void run() {
while (true) {
String json = MessageCahce.take();
log.info(json);
ChannelHandlerPool.send2All(new TextWebSocketFrame(json));
if (json.contains("0060")){
log.info("已推送干扰数据:");
}
else if(json.contains("0061")){
log.info("已推送功放数据:");
}
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Netty-Websocket</title>
</head>
<script src="webjars/jquery/3.4.1/jquery.js"></script>
<script type="text/javascript">
var socket;
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if (window.WebSocket) {
socket = new WebSocket("ws://222.222.216.210:7777/websocket");
socket.onmessage = function (event) {
console.log(event.data)
};
socket.onopen = function (event) {
console.log("Netty-WebSocket服务器。。。。。。连接")
};
socket.onclose = function (event) {
console.log("Netty-WebSocket服务器。。。。。。关闭")
};
} else {
alert("您的浏览器不支持WebSocket协议!");
}
</script>
<body>
<div id="ws" class="ws">
</div>
</body>
</html>